diff --git a/dist/doboard-widget-bundle.js b/dist/doboard-widget-bundle.js
index 327d961..78ec904 100644
--- a/dist/doboard-widget-bundle.js
+++ b/dist/doboard-widget-bundle.js
@@ -250,6 +250,11 @@ const spotfixApiCall = async(data, method, accountId = undefined) => {
if (responseBody.data.operation_status === 'FAILED') {
const errorMessage = responseBody.data.operation_message || 'Operation failed without specific message';
+ if(responseBody?.data?.operation_message === 'session_id Unknown'){
+ clearLocalstorageOnLogout();
+ checkLogInOutButtonsVisible();
+ await deleteDB();
+ }
throw new Error(errorMessage);
}
@@ -351,6 +356,7 @@ const registerUserDoboard = async (projectToken, accountId, email, nickname, pag
operationMessage: result.operation_message,
operationStatus: result.operation_status,
userEmailConfirmed: result.user_email_confirmed,
+ accounts: result.accounts,
};
};
@@ -368,11 +374,24 @@ const loginUserDoboard = async (email, password) => {
operationMessage: result.operation_message,
operationStatus: result.operation_status,
userEmailConfirmed: result.user_email_confirmed,
+ accounts: result.accounts
}
}
-const logoutUserDoboard = async (projectToken, accountId) => {
+const forgotPasswordDoboard = async (email) => {
+ const data = {
+ email: email
+ }
+ return await spotfixApiCall(data, 'user_password_reset');
+}
+
+
+const logoutUserDoboard = async (projectToken) => {
const sessionId = localStorage.getItem('spotfix_session_id');
+ const accountsString = localStorage.getItem('spotfix_accounts');
+ const accounts = accountsString !== 'undefined' ? JSON.parse(accountsString || '[]') : [];
+ const accountId = accounts.length > 0 ? accounts[0].account_id : 1;
+
if(sessionId && accountId) {
const data = {
session_id: sessionId,
@@ -389,6 +408,7 @@ const logoutUserDoboard = async (projectToken, accountId) => {
if (result.operation_status === 'SUCCESS') {
await deleteDB();
clearLocalstorageOnLogout();
+ checkLogInOutButtonsVisible();
}
}
}
@@ -642,6 +662,7 @@ const wsSpotfix = {
const SPOTFIX_VERSION = "1.1.5";
+let spotFixCSS = `.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:"";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:40px;margin-top:10px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-hidden,.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login .doboard_task_widget-login-icon{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active .doboard_task_widget-login-icon{margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-login-icon::after{position:absolute;top:0;right:4px;content:"";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-login-icon::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{min-height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-login-buttons-wrapper{display:flex;gap:10px;margin-bottom:10px}.doboard_task_widget-login-buttons-wrapper .doboard_task_widget-submit_button{margin-bottom:0;width:auto;min-height:32px;font-size:14px;padding:4px 12px}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page{flex:1;background:#FFF;border:1px solid #22A475;color:#22A475}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black:hover,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page:hover{background:#f0fdf4;color:#1C7857}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-login_button,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-restore_password_button{flex:2}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:"";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:"";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:"wght" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:""}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:"";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.doboard_task_widget-bottom-eye-icon,.doboard_task_widget-bottom-eye-off-icon{position:absolute;right:10px;top:50%;transform:translateY(-50%);width:20px;height:20px;cursor:pointer;border-radius:50%;transition:all .2s ease;z-index:10}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}.doboard_task_widget-forgot_password,.doboard_task_widget-on_phantom_login_page,.doboard_task_widget-show_login_form{display:inline-block;cursor:pointer;color:#2F68B7;margin-bottom:0}.doboard_task_widget-forgot_password{margin-bottom:20px}.doboard_task_widget-login-is-invalid{color:red}.doboard_task_widget-forgot_password_form-menu,.doboard_task_widget-input-container-login-menu{margin:20px}.doboard_task_widget-bottom-eye-icon{background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMjAgMjAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDIwIDIwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBkPSJNMTAsMTcuNGMtNi4yLDAtOS43LTYuOC05LjgtNy4xYy0wLjEtMC4yLTAuMS0wLjUsMC0wLjdDMC4zLDkuNCwzLjgsMi42LDEwLDIuNmM2LjIsMCw5LjcsNi44LDkuOCw3LjENCgljMC4xLDAuMiwwLjEsMC41LDAsMC43QzE5LjcsMTAuNiwxNi4yLDE3LjQsMTAsMTcuNHogTTEuNywxMGMwLjgsMS4zLDMuNyw1LjksOC4zLDUuOWM0LjYsMCw3LjYtNC42LDguMy01LjkNCgljLTAuOC0xLjMtMy43LTUuOS04LjMtNS45QzUuNCw0LjEsMi40LDguNywxLjcsMTB6IE0xMCwxMy4zYy0xLjgsMC0zLjMtMS41LTMuMy0zLjNTOC4yLDYuOCwxMCw2LjhzMy4zLDEuNSwzLjMsMy4zDQoJUzExLjgsMTMuMywxMCwxMy4zeiBNMTAsOC4zQzksOC4zLDguMyw5LDguMywxMFM5LDExLjgsMTAsMTEuOHMxLjgtMC44LDEuOC0xLjhTMTEsOC4zLDEwLDguM3oiLz4NCjwvc3ZnPg0K) center center no-repeat #fff;background-size:16px 16px}.doboard_task_widget-bottom-eye-off-icon{background:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDIwIDIwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyMCAyMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE2LjgsMTMuMmMwLjEsMC4xLDAuMywwLjIsMC41LDAuMmMwLDAsMCwwLDAsMGMwLjIsMCwwLjQtMC4xLDAuNS0wLjNjMC43LTAuOSwxLjQtMS44LDEuOS0yLjgNCgljMC4xLTAuMiwwLjEtMC41LDAtMC43Yy0wLjEtMC4zLTMuNi03LjEtOS44LTcuMWMwLDAsMCwwLDAsMGMtMC42LDAtMS4zLDAuMS0xLjksMC4yQzcuOCwyLjksNy42LDMuMSw3LjUsMy4zczAsMC41LDAuMiwwLjcNCglMMTYuOCwxMy4yeiBNMTAsNC4xYzQuNiwwLDcuNiw0LjYsOC4zLDUuOWMtMC4zLDAuNS0wLjYsMS0xLDEuNUw5LjksNC4xQzkuOSw0LjEsMTAsNC4xLDEwLDQuMXogTTE5LjcsMTguNmwtNC4yLTQuMkw1LjYsNC41DQoJYzAsMCwwLDAsMCwwTDEuNCwwLjNDMS4xLDAsMC42LDAsMC4zLDAuM1MwLDEuMSwwLjMsMS40TDMuOSw1QzIuNCw2LjMsMS4xLDcuOSwwLjIsOS42Yy0wLjEsMC4yLTAuMSwwLjUsMCwwLjcNCgljMC4xLDAuMywzLjYsNy4xLDkuOSw3LjFjMS43LDAsMy40LTAuNSw0LjktMS41bDMuOCwzLjhjMC4xLDAuMSwwLjMsMC4yLDAuNSwwLjJzMC40LTAuMSwwLjUtMC4yQzIwLDE5LjQsMjAsMTguOSwxOS43LDE4LjZ6DQoJIE04LjMsOS40bDIuMywyLjNjLTAuMiwwLjEtMC40LDAuMS0wLjYsMC4xYy0wLjIsMC0wLjUsMC0wLjctMC4xYy0wLjItMC4xLTAuNC0wLjItMC42LTAuNGMtMC4yLTAuMi0wLjMtMC40LTAuNC0wLjYNCgljLTAuMS0wLjItMC4xLTAuNS0wLjEtMC43QzguMiw5LjgsOC4yLDkuNiw4LjMsOS40eiBNMTAsMTUuOWMtNC42LDAtNy42LTQuNi04LjMtNS45YzAuOS0xLjUsMi0yLjgsMy4zLTMuOWwyLjIsMi4yDQoJQzcuMSw4LjQsNyw4LjYsNyw4LjdDNi44LDkuMSw2LjcsOS42LDYuNywxMGMwLDAuNCwwLjEsMC45LDAuMiwxLjNjMC4yLDAuNCwwLjQsMC44LDAuNywxLjFjMC4zLDAuMywwLjcsMC42LDEuMSwwLjcNCgljMC40LDAuMiwwLjgsMC4yLDEuMywwLjJjMC40LDAsMC45LTAuMSwxLjMtMC4zYzAuMi0wLjEsMC4zLTAuMiwwLjUtMC4zbDIuMSwyLjFDMTIuNiwxNS41LDExLjMsMTUuOSwxMCwxNS45eiIvPg0KPC9zdmc+DQo=) center center no-repeat #fff;background-size:16px 16px;opacity:.5}`;
async function confirmUserEmail(emailConfirmationToken, params) {
const result = await userConfirmEmailDoboard(emailConfirmationToken);
@@ -856,15 +877,23 @@ function registerUser(taskDetails) {
localStorage.setItem('spotfix_session_id', response.sessionId);
localStorage.setItem('spotfix_user_id', response.userId);
localStorage.setItem('spotfix_email', response.email);
+ localStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));
spotfixIndexedDB.init();
userUpdate(projectToken, accountId);
} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {
- if (response.operationMessage == 'Waiting for email confirmation') {
+ if (response.operationMessage === 'Waiting for email confirmation') {
response.operationMessage = 'Waiting for an email confirmation. Please check your Inbox.';
+ if (document.getElementById('doboard_task_widget-error_message').innerText === 'Waiting for an email confirmation. Please check your Inbox.') {
+ response.operationMessage = 'Incorrect email address. Please confirm your email to create the spot.';
+ }
}
if (typeof showMessageCallback === 'function') {
showMessageCallback(response.operationMessage, 'notice');
}
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ submitButton.disabled = true;
+ submitButton.innerText = ksesFilter('Create spot');
+
} else {
throw new Error('Session ID not found in response');
}
@@ -885,7 +914,10 @@ function loginUser(taskDetails) {
if (response.sessionId) {
localStorage.setItem('spotfix_session_id', response.sessionId);
localStorage.setItem('spotfix_user_id', response.userId);
+ localStorage.setItem('spotfix_email', response.email);
localStorage.setItem('spotfix_email', userEmail);
+ localStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));
+ checkLogInOutButtonsVisible();
spotfixIndexedDB.init();
} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {
if (typeof showMessageCallback === 'function') {
@@ -900,6 +932,33 @@ function loginUser(taskDetails) {
});
}
+function forgotPassword(userEmail) {
+ return (showMessageCallback) => forgotPasswordDoboard(userEmail)
+ .then(response => {
+ console.log('response ', response)
+ if (response?.operation_status === 'SUCCESS') {
+ showMessageCallback('New password sent to email', 'notice');
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ } else {
+ throw new Error('Response error');
+ }
+ })
+ .catch(error => {
+ throw error;
+ });
+}
+
function userUpdate(projectToken, accountId) {
const sessionId = localStorage.getItem('spotfix_session_id');
const userId = localStorage.getItem('spotfix_user_id');
@@ -935,7 +994,6 @@ function setToggleStatus(rootElement){
const clickHandler = () => {
const timer = setTimeout(() => {
localStorage.setItem('spotfix_widget_is_closed', '1');
- wsSpotfix.close();
rootElement.hide();
clearTimeout(timer);
}, 300);
@@ -949,13 +1007,40 @@ function setToggleStatus(rootElement){
function checkLogInOutButtonsVisible (){
if(!localStorage.getItem('spotfix_session_id')) {
- const el = document
- .getElementById('doboard_task_widget-user_menu-logout_button')
- ?.closest('.doboard_task_widget-user_menu-item');
- if(el) el.style.display = 'none';
- } else {
- const el = document.getElementById('doboard_task_widget-user_menu-signlog_button');
+ const el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');
if(el) el.style.display = 'none';
+
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login')
+ if(loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ clearUserMenuData();
+ } else {
+ const el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');
+ if(el) el.style.display = 'block';
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login')
+ if(loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ }
+}
+
+/**
+ * Clear user menu data in menu
+ */
+async function clearUserMenuData() {
+ const userNameElement = document.querySelector('.doboard_task_widget-user_menu-header-user-name');
+ const emailElement = document.querySelector('.doboard_task_widget-user_menu-header-email');
+ const avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');
+
+ if (userNameElement) {
+ userNameElement.innerText = 'Guest';
+ }
+ if (emailElement) {
+ emailElement.innerText = '';
+ }
+ if (avatarElement) {
+ avatarElement.src = SpotFixSVGLoader.getAsDataURI('iconAvatar');
}
}
@@ -967,7 +1052,6 @@ function changeSize(container){
}
}
-let spotFixCSS = `.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:"";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:65px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login span{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active span{margin-bottom:24px}.doboard_task_widget-login span::after{position:absolute;top:0;right:4px;content:"";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active span::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:"";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:"";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:"wght" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:""}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:"";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}`;
/**
* Widget class to create a task widget
*/
@@ -1127,8 +1211,9 @@ class CleanTalkWidgetDoboard {
let userEmail = '';
let userPassword = '';
const loginSectionElement = document.querySelector('.doboard_task_widget-login');
+ const sessionIdExists = !!localStorage.getItem('spotfix_session_id');
- if ( loginSectionElement && loginSectionElement.classList.contains('active') ) {
+ if ( !sessionIdExists && loginSectionElement && loginSectionElement.classList.contains('active') ) {
const userEmailElement = document.getElementById('doboard_task_widget-user_email');
const userNameElement = document.getElementById('doboard_task_widget-user_name');
const userPasswordElement = document.getElementById('doboard_task_widget-user_password');
@@ -1241,6 +1326,233 @@ class CleanTalkWidgetDoboard {
}
}
+
+ resetLoginForm() {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ }
+ }
+ bindShowLoginFormEvents() {
+ const showLoginButton = document.getElementById('doboard_task_widget-show_login_form');
+ const showPhantomLoginButton = document.getElementById('doboard_task_widget-on_phantom_login_page');
+ const forgotPasswordButton = document.getElementById('doboard_task_widget-forgot_password');
+ const forgotPasswordButtonBlack = document.getElementById('doboard_task_widget-forgot_password-black');
+ const loginButton = document.getElementById('doboard_task_widget-login_button');
+ const restorePasswordButton = document.getElementById('doboard_task_widget-restore_password_button');
+
+ if (showLoginButton) {
+ showLoginButton.addEventListener('click', async () => {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (loginContainer) {
+ loginContainer.classList.toggle('doboard_task_widget-hidden');
+ if (submitButton) {
+ if (loginContainer.classList.contains('doboard_task_widget-hidden')) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ } else {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.toggle('doboard_task_widget-hidden');
+ }
+ })
+ }
+ if (showPhantomLoginButton) {
+ showPhantomLoginButton.addEventListener('click', async () => {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (loginContainer) {
+ loginContainer.classList.toggle('doboard_task_widget-hidden');
+ if (submitButton) {
+ if (loginContainer.classList.contains('doboard_task_widget-hidden')) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ } else {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.toggle('doboard_task_widget-hidden');
+ }
+ })
+ }
+ if (forgotPasswordButton) {
+ forgotPasswordButton.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.remove('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ })
+
+ forgotPasswordButtonBlack.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ })
+ }
+ const forgotPasswordButtonMenu = document.querySelector('.doboard_task_widget-input-container-login-menu #doboard_task_widget-forgot_password');
+ if (forgotPasswordButtonMenu) {
+ forgotPasswordButtonMenu.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.remove('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ });
+ }
+ const forgotPasswordButtonBlackMenu = document.querySelector('.doboard_task_widget-input-container-login-menu ~ #doboard_task_widget-container-login-forgot-password-form #doboard_task_widget-forgot_password-black');
+ if (forgotPasswordButtonBlackMenu) {
+ forgotPasswordButtonBlackMenu.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ });
+ }
+ if (loginButton) {
+ loginButton.addEventListener('click', async () => {
+ const userEmailElement = document.getElementById('doboard_task_widget-login_email');
+ const userPasswordElement = document.getElementById('doboard_task_widget-login_password');
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.add('doboard_task_widget-hidden');
+
+ const userEmail = userEmailElement.value.trim();
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!userEmail) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (!emailRegex.test(userEmail)) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ }
+
+ const userPassword = userPasswordElement.value;
+ if (!userPassword) {
+ userPasswordElement.style.borderColor = 'red';
+ userPasswordElement.focus();
+ userPasswordElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (userPassword.length < 6) {
+ userPasswordElement.style.borderColor = 'red';
+ userPasswordElement.focus();
+ userPasswordElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ }
+
+ try {
+ await loginUser({
+ userEmail: userEmail,
+ userPassword: userPassword
+ })(this.registrationShowMessage);
+ this.setUserMenuData();
+
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ }
+
+ } catch (error) {
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');
+ }
+ const sessionIdExists = !!localStorage.getItem('spotfix_session_id');
+ const email = localStorage.getItem('spotfix_email');
+ if (sessionIdExists && email && !email.includes('spotfix_')) {
+ const loginEl= document.querySelector('.doboard_task_widget-login');
+ loginEl?.classList?.add('doboard_task_widget-hidden');
+ } else {
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');
+ }
+ })
+ }
+ const passwordToggle = document.getElementById('doboard_task_widget-password-toggle');
+ const passwordInput = document.getElementById('doboard_task_widget-login_password');
+
+ if (passwordToggle && passwordInput) {
+ passwordToggle.addEventListener('click', function() {
+ const isPassword = passwordInput.type === 'password';
+ passwordInput.type = isPassword ? 'text' : 'password';
+ this.classList.toggle('doboard_task_widget-bottom-eye-off-icon');
+ this.classList.toggle('doboard_task_widget-bottom-eye-icon');
+ });
+ }
+ if (restorePasswordButton) {
+ restorePasswordButton.addEventListener('click', async () => {
+ const userEmailElement = document.getElementById('doboard_task_widget-forgot_password_email');
+ const userEmail = userEmailElement.value.trim();
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!userEmail) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (!emailRegex.test(userEmail)) {
+
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+
+ return;
+ }
+
+ try {
+ await forgotPassword(userEmail)(this.registrationShowMessage);
+ } catch (error) {
+ this.registrationShowMessage(error.message, 'error');
+ }
+ })
+ }
+ }
+
/**
* Create widget element
* @return {HTMLElement} widget element
@@ -1361,6 +1673,7 @@ class CleanTalkWidgetDoboard {
}
// bind creation events
this.bindCreateTaskEvents();
+ this.bindShowLoginFormEvents();
break;
case 'wrap':
await this.getTaskCount();
@@ -1510,6 +1823,8 @@ class CleanTalkWidgetDoboard {
document.body.appendChild(widgetContainer);
setToggleStatus(this);
checkLogInOutButtonsVisible();
+ this.bindShowLoginFormEvents();
+ this.bindWidgetInputsInteractive();
break;
case 'concrete_issue':
@@ -1713,7 +2028,7 @@ class CleanTalkWidgetDoboard {
}) || '';
document.querySelector('#doboard_task_widget-user_menu-logout_button')?.addEventListener('click', () => {
- logoutUserDoboard(this.params.projectToken, this.params.accountId).then(() => {this.hide()});
+ logoutUserDoboard(this.params.projectToken);
}) || '';
document.getElementById('addNewTaskButton')?.addEventListener('click', () => {
@@ -1738,6 +2053,7 @@ class CleanTalkWidgetDoboard {
document.querySelector('#spotfix_back_button')?.addEventListener('click', () => {
this.createWidgetElement(this.type_name)
+ this.bindWidgetInputsInteractive();
}) || '';
return widgetContainer;
@@ -1888,6 +2204,7 @@ class CleanTalkWidgetDoboard {
await registerUser(taskDetails)(this.registrationShowMessage);
if ( taskDetails.userPassword ) {
await loginUser(taskDetails)(this.registrationShowMessage);
+ checkLogInOutButtonsVisible();
}
}
@@ -2077,6 +2394,54 @@ class CleanTalkWidgetDoboard {
}
return '';
}
+
+/**
+ * Set user menu data with current user information
+ */
+async setUserMenuData() {
+ const params = this.params;
+
+ // Get user data
+ let userData = null;
+ if (localStorage.getItem('spotfix_session_id')) {
+ try {
+ userData = await getUserDetails(params);
+ } catch (error) {
+ console.error('Error fetching user details:', error);
+ }
+ }
+
+ // Update user menu header
+ const userNameElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 16px"]');
+ const emailElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 12px"]');
+ const avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');
+
+ if (userNameElement) {
+ if (userData && userData.name) {
+ userNameElement.innerText = userData.name;
+ } else {
+ userNameElement.innerText = 'Guest';
+ }
+ }
+
+ if (emailElement) {
+ if (userData && userData.email) {
+ emailElement.innerText = userData.email;
+ } else {
+ const email = localStorage.getItem('spotfix_email') || '';
+ emailElement.innerText = email.includes('spotfix_') ? '' : email;
+ }
+ }
+
+ if (avatarElement) {
+ if (userData && userData.avatar && userData.avatar.s) {
+ avatarElement.src = userData.avatar.s;
+ } else {
+ // Reset to default avatar or remove src
+ avatarElement.src = '';
+ }
+ }
+}
}
var spotFixShowDelayTimeout = null;
@@ -3226,6 +3591,7 @@ function clearLocalstorageOnLogout () {
localStorage.removeItem('spotfix_email');
localStorage.removeItem('spotfix_session_id');
localStorage.removeItem('spotfix_user_id');
+ localStorage.removeItem('spotfix_accounts');
localStorage.setItem('spotfix_widget_is_closed', '1');
wsSpotfix.close();
}
@@ -3794,27 +4160,64 @@ class SpotFixTemplatesLoader {
- {{userName}}
- {{email}}
-
+
+
@@ -3908,6 +4308,38 @@ class SpotFixTemplatesLoader {
Log out
+
+
+
+
@@ -3917,6 +4349,10 @@ class SpotFixTemplatesLoader {
doBoard
+
`;
}
diff --git a/dist/doboard-widget-bundle.min.js b/dist/doboard-widget-bundle.min.js
index 3c5804b..32fe439 100644
--- a/dist/doboard-widget-bundle.min.js
+++ b/dist/doboard-widget-bundle.min.js
@@ -1,10 +1,10 @@
-let INDEXED_DB_NAME="spotfix-localDB",indexedDBVersion=1,TABLE_USERS="users",TABLE_TASKS="tasks",TABLE_COMMENTS="comments",LOCAL_DATA_BASE_TABLE=[{name:TABLE_USERS,keyPath:"user_id"},{name:TABLE_TASKS,keyPath:"taskId"},{name:TABLE_COMMENTS,keyPath:"commentId"}];async function openIndexedDB(o,i=indexedDBVersion){return new Promise((t,e)=>{let a=indexedDB.open(o,i);a.onsuccess=()=>t(a.result),a.onerror=()=>e(a.error),a.onupgradeneeded=e=>t(a.result)})}async function deleteDB(){try{for(let a of await window.indexedDB.databases())await new Promise(e=>{var t=indexedDB.deleteDatabase(a.name);t.onsuccess=()=>e(),t.onerror=()=>e()})}catch(e){console.warn("deleteDB error",e)}}let spotfixIndexedDB={getIndexedDBName:()=>INDEXED_DB_NAME+"_"+(localStorage.getItem("spotfix_session_id")||localStorage.getItem("spotfix_project_token")),error:(e,t)=>{console.error("IndexedDB error",e,t)},init:async()=>{var e=localStorage.getItem("spotfix_session_id"),t=localStorage.getItem("spotfix_project_token");if(!e&&!t)return{needInit:!1};let s=spotfixIndexedDB.getIndexedDBName();return await deleteDB(),new Promise((i,a)=>{var e=indexedDB.open(s,indexedDBVersion);e.onupgradeneeded=e=>{let a=e.target.result;LOCAL_DATA_BASE_TABLE.forEach(e=>{var t;a.objectStoreNames.contains(e.name)||(t=a.createObjectStore(e.name,{keyPath:e.keyPath}),e.name===TABLE_COMMENTS&&t.createIndex("taskId","taskId"),e.name===TABLE_TASKS&&t.createIndex("userId","userId"))}),i({needInit:!0})},e.onsuccess=e=>{let t=e.target.result,o=LOCAL_DATA_BASE_TABLE.filter(e=>!t.objectStoreNames.contains(e.name));0===o.length?(t.close(),i({needInit:!0})):(e=t.version+1,t.close(),(e=indexedDB.open(s,e)).onupgradeneeded=e=>{let a=e.target.result;o.forEach(e=>{var t=a.createObjectStore(e.name,{keyPath:e.keyPath});e.name===TABLE_COMMENTS&&t.createIndex("taskId","taskId"),e.name===TABLE_TASKS&&t.createIndex("userId","userId")})},e.onsuccess=()=>i({needInit:!0}),e.onerror=e=>a(e))},e.onerror=e=>a(e)})},withStore:async(s,r="readwrite",d)=>{let n=await openIndexedDB(spotfixIndexedDB.getIndexedDBName(),indexedDBVersion);return new Promise((t,a)=>{try{var o=n.transaction(s,r),i=o.objectStore(s);let e=d(i);o.oncomplete=()=>{n.close(),t(e)},o.onerror=e=>{n.close(),a(e.target.error)}}catch(e){n.close(),a(e)}})},put:async(e,a)=>spotfixIndexedDB.withStore(e,"readwrite",t=>{Array.isArray(a)?a.forEach(e=>t.put(e)):t.put(a)}),delete:async(e,t)=>spotfixIndexedDB.withStore(e,"readwrite",e=>{e.delete(t)}),clearTable:async e=>spotfixIndexedDB.withStore(e,"readwrite",e=>e.clear()),clearPut:async(e,t)=>{await spotfixIndexedDB.clearTable(e),await spotfixIndexedDB.put(e,t)},getAll:async(e,i,s)=>spotfixIndexedDB.withStore(e,"readonly",o=>new Promise((e,t)=>{let a;(a=i&&void 0!==s?o.index(i).getAll(s):o.getAll()).onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})),getTable:async e=>localStorage.getItem("spotfix_session_id")||localStorage.getItem("spotfix_project_token")?spotfixIndexedDB.getAll(e):[],deleteTable:async(e,t)=>spotfixIndexedDB.delete(e,t)},SPOTFIX_DOBOARD_API_URL="https://api.doboard.com",spotfixApiCall=async(e,t,a=void 0)=>{if(!e||"object"!=typeof e)throw new Error("Data must be a valid object");if(!t||"string"!=typeof t)throw new Error("Method must be a valid string");if(void 0!==a&&"string"!=typeof a&&"number"!=typeof a)throw new Error("AccountId must be a string or number");var o,i=new FormData;for(o in e)e.hasOwnProperty(o)&&null!=e[o]&&i.append(o,e[o]);let s;s=void 0!==a?SPOTFIX_DOBOARD_API_URL+`/${a}/`+t:SPOTFIX_DOBOARD_API_URL+"/"+t;try{new URL(s)}catch(e){throw new Error("Invalid endpoint URL: "+s)}let r;try{r=await fetch(s,{method:"POST",body:i})}catch(e){throw new Error("Network error: "+e.message)}let d;try{d=await r.json()}catch(e){throw new Error("Failed to parse JSON response from server")}if(!d||"object"!=typeof d)throw new Error("Invalid response format from server");if(!d.data)throw new Error("Missing data field in server response");if(!d.data.operation_status)throw new Error("Missing operation_status in response data");if("FAILED"===d.data.operation_status)throw a=d.data.operation_message||"Operation failed without specific message",new Error(a);if("SUCCESS"===d.data.operation_status)return d.data;throw new Error("Unknown operation status: "+d.data.operation_status)},userConfirmEmailDoboard=async e=>{e={email_confirmation_token:encodeURIComponent(e)},e=await spotfixApiCall(e,"user_confirm_email");return{sessionId:e.session_id,userId:e.user_id,email:e.email,accounts:e.accounts,operationStatus:e.operation_status}},createTaskDoboard=async(e,t)=>{var a=t.accountId,e={session_id:e,project_token:t.projectToken,project_id:t.projectId,user_id:localStorage.getItem("spotfix_user_id"),name:t.taskTitle,comment:t.taskDescription,meta:t.taskMeta,task_type:"PUBLIC"};return{taskId:(await spotfixApiCall(e,"task_add",a)).task_id}},createTaskCommentDoboard=async(e,t,a,o,i,s="ACTIVE")=>{t={session_id:t,project_token:i,task_id:a,comment:o,status:s};return{commentId:(await spotfixApiCall(t,"comment_add",e)).comment_id}},attachmentAddDoboard=async e=>{var t=e.params.accountId,e={session_id:e.sessionId,project_token:e.params.projectToken,account_id:e.params.accountId,comment_id:e.commentId,filename:e.fileName,file:e.fileBinary,attachment_order:e.attachmentOrder};await spotfixApiCall(e,"attachment_add",t)},registerUserDoboard=async(t,e,a,o,i)=>{t={project_token:t,account_id:e,confirmation_url:a};if(a&&o&&(t.email=a,t.name=o),localStorage.getItem("bot_detector_event_token"))try{var s=JSON.parse(localStorage.getItem("bot_detector_event_token"));s?.value&&(t.bot_detector_event_token=s?.value)}catch(e){t.bot_detector_event_token=""}e=await spotfixApiCall(t,"user_registration");return{sessionId:e.session_id,userId:e.user_id,email:e.email,accountExists:1===e.user_email_confirmed,operationMessage:e.operation_message,operationStatus:e.operation_status,userEmailConfirmed:e.user_email_confirmed}},loginUserDoboard=async(e,t)=>{e={email:e,password:t},t=await spotfixApiCall(e,"user_authorize");return{sessionId:t.session_id,userId:t.user_id,email:t.email,accountExists:1===t.user_email_confirmed,operationMessage:t.operation_message,operationStatus:t.operation_status,userEmailConfirmed:t.user_email_confirmed}},logoutUserDoboard=async(e,t)=>{var a,o=localStorage.getItem("spotfix_session_id");o&&t&&(o={session_id:o},(a=localStorage.getItem("spotfix_email")||"")&&a.includes("spotfix_")&&(o.project_token=e),"SUCCESS"===(await spotfixApiCall(o,"user_unauthorize",t)).operation_status)&&(await deleteDB(),clearLocalstorageOnLogout())},getTasksDoboard=async(e,t,a,o,i)=>{t={session_id:t,project_token:e,project_id:o,task_type:"PUBLIC",status:"ACTIVE,DONE"};i&&(t.user_id=i);e=(await spotfixApiCall(t,"task_get",a)).tasks.map(e=>({taskId:e.task_id,taskTitle:e.name,userId:e.user_id,taskLastUpdate:e.updated,taskCreated:e.created,taskCreatorTaskUser:e.creator_user_id,taskMeta:e.meta,taskStatus:e.status}));return await spotfixIndexedDB.clearPut(TABLE_TASKS,e),storageSaveTasksCount(e),e},getTasksCommentsDoboard=async(e,t,a,o="ACTIVE")=>{e={session_id:e,project_token:a,status:o},a=(await spotfixApiCall(e,"comment_get",t)).comments.map(e=>({taskId:e.task_id,commentId:e.comment_id,userId:e.user_id,commentBody:e.comment,commentDate:e.updated,status:e.status,issueTitle:e.task_name}));return await spotfixIndexedDB.clearPut(TABLE_COMMENTS,a),a},getUserDoboard=async(e,t,a,o)=>{e={session_id:e,project_token:t},o&&(e.user_id=o),t=await spotfixApiCall(e,"user_get",a);return e.user_id?await spotfixIndexedDB.put(TABLE_USERS,t.users):await spotfixIndexedDB.clearPut(TABLE_USERS,t.users),t.users},userUpdateDoboard=async(e,t,a,o,i)=>{a={session_id:a,project_token:e,user_id:o,timestamp:i};return await spotfixApiCall(a,"user_update",t),{success:!0}},getReleaseVersion=async()=>{try{var e=await(await fetch("https://api.github.com/repos/CleanTalk/SpotFix/releases")).json();return 0localStorage.getItem("spotfix_session_id"),buildMessage=e=>({channel:"account:"+localStorage.getItem("spotfix_company_id"),action:e,account_id:localStorage.getItem("spotfix_company_id"),session_id:getSessionId(),project_token:localStorage.getItem("spotfix_project_token")}),wsSpotfix={connect(){socket&&socket.readyState===WebSocket.OPEN||!getSessionId()||((socket=new WebSocket(WS_URL)).onopen=()=>{heartbeatInterval=setInterval(()=>{socket?.readyState===WebSocket.OPEN&&socket.send("heartbeat")},5e4),wsSpotfix.send(buildMessage("SUBSCRIBE"))},socket.onmessage=t=>{if("heartbeat"!==t.data)try{var e=JSON.parse(t.data);switch(e.object){case"users":spotfixIndexedDB.put(TABLE_USERS,e.data);break;case"tasks":"REMOVED"===e.data.status?spotfixIndexedDB.delete(TABLE_TASKS,e.data.task_id):spotfixIndexedDB.put(TABLE_TASKS,{taskId:e.data.task_id,taskTitle:e.data.name,userId:e.data.user_id,taskLastUpdate:e.data.updated,taskCreated:e.data.created,taskCreatorTaskUser:e.data.creator_user_id,taskMeta:e.data.meta,taskStatus:e.data.status});break;case"comments":"REMOVED"===e.data.status?spotfixIndexedDB.delete(TABLE_COMMENTS,e.data.comment_id):spotfixIndexedDB.put(TABLE_COMMENTS,{taskId:e.data.task_id,commentId:e.data.comment_id,userId:e.data.user_id,commentBody:e.data.comment,commentDate:e.data.updated,status:e.data.status,issueTitle:e.data.task_name})}}catch(e){console.warn("WS non-JSON message:",t.data)}},socket.onclose=e=>{console.warn("WS closed:",e.code,e.reason),socket=null,heartbeatInterval&&(clearInterval(heartbeatInterval),heartbeatInterval=null)},socket.onerror=e=>{console.error("WS error:",e)})},send(e){socket&&socket.readyState===WebSocket.OPEN?socket.send(JSON.stringify(e)):console.warn("WebSocket is not connected")},close(){wsSpotfix.unsubscribe(),socket?.close()},subscribe(){socket?.readyState===WebSocket.OPEN&&wsSpotfix.send(buildMessage("SUBSCRIBE"))},unsubscribe(){socket?.readyState===WebSocket.OPEN&&wsSpotfix.send(buildMessage("UNSUBSCRIBE"))}},SPOTFIX_VERSION="1.1.5";async function confirmUserEmail(e,t){var e=await userConfirmEmailDoboard(e),a=(localStorage.setItem("spotfix_email",e.email),localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),await spotfixIndexedDB.init(),localStorage.getItem("spotfix_pending_task"));if(!a)throw new Error("No pending task data");let o;try{o=JSON.parse(a)}catch(e){throw new Error("Invalid pending task data")}a={taskTitle:o.selectedText||"New Task",taskDescription:o.description||"",selectedData:o,projectToken:t.projectToken,projectId:t.projectId,accountId:t.accountId,taskMeta:JSON.stringify(o)},t=await handleCreateTask(e.sessionId,a);return localStorage.removeItem("spotfix_pending_task"),t}async function getTasksFullDetails(e,t,a){var o,i;if(0+e.taskId==+a)?.taskStatus}}async function getUserDetails(e){var t=localStorage.getItem("spotfix_session_id");let a=localStorage.getItem("spotfix_user_id");if(a)return await getUserDoboard(t,e.projectToken,e.accountId,a),(await spotfixIndexedDB.getAll(TABLE_USERS)).find(e=>+e.user_id==+a)||{}}async function handleCreateTask(e,t){try{var a,o=await createTaskDoboard(e,t);return o&&o.taskId&&t.taskDescription&&(a=`The spot has been posted at the following URL ${window.location.href} `,await addTaskComment({projectToken:t.projectToken,accountId:t.accountId},o.taskId,t.taskDescription+a)),o}catch(e){throw e}}async function addTaskComment(e,t,a){var o=localStorage.getItem("spotfix_session_id");if(!o)throw new Error("No session");if(e.projectToken&&e.accountId)return createTaskCommentDoboard(e.accountId,o,t,a,e.projectToken);throw new Error("Missing params")}async function getUserTasks(e){var t,a,o;return localStorage.getItem("spotfix_session_id")?(t=e.projectToken,a=localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_user_id"),await getTasksDoboard(t,a,e.accountId,e.projectId,o),spotfixIndexedDB.getAll(TABLE_TASKS,"userId",o)):{}}async function getAllTasks(e){var t,a;return localStorage.getItem("spotfix_session_id")?(t=e.projectToken,a=localStorage.getItem("spotfix_session_id"),await getTasksDoboard(t,a,e.accountId,e.projectId),(await spotfixIndexedDB.getAll(TABLE_TASKS)).filter(e=>e.taskMeta)):{}}function formatDate(e){if(!e)return{date:"",time:""};let t;return t=!e.includes("T")&&e.includes(" ")?new Date(e.replace(" ","T")):new Date(e),isNaN(t.getTime())?{date:"",time:""}:(e=t.getTimezoneOffset(),{date:["January","February","March","April","May","June","July","August","September","October","November","December"][(e=new Date(t.getTime()-6e4*e)).getMonth()]+" "+e.getDate(),time:e.getHours().toString().padStart(2,"0")+":"+e.getMinutes().toString().padStart(2,"0")})}function getTaskAuthorDetails(e,t){localStorage.getItem("spotfix_session_id");var a=[{taskId:"1",taskAuthorAvatarImgSrc:"https://s3.eu-central-1.amazonaws.com/cleantalk-ctask-atts/accounts/1/avatars/081a1b65d20fe318/m.jpg",taskAuthorName:"Test All Issues Single Author Name"}].find(e=>e.taskId===t);return void 0===a?{taskId:null,taskAuthorAvatarImgSrc:null,taskAuthorName:"Task Author"}:a}function getIssuesCounterString(e,t){return` (${e}/${t})`}function getAvatarSrc(e){if(e&&e.avatar){if("object"==typeof e.avatar&&e.avatar.m)return e.avatar.m;if("string"==typeof e.avatar)return e.avatar}return null}function getAuthorName(e){if(e){if(e.name&&0registerUserDoboard(i,s,a,o,r).then(e=>{if(e.accountExists)document.querySelector(".doboard_task_widget-accordion>.doboard_task_widget-input-container").innerText=ksesFilter("Account already exists. Please, login usin your password."),document.querySelector(".doboard_task_widget-accordion>.doboard_task_widget-input-container.hidden").classList.remove("hidden"),document.getElementById("doboard_task_widget-user_password").focus();else if(e.sessionId)localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),localStorage.setItem("spotfix_email",e.email),spotfixIndexedDB.init(),userUpdate(i,s);else{if(!("SUCCESS"===e.operationStatus&&e.operationMessage&&0{throw e})}function loginUser(e){let a=e.userEmail,o=e.userPassword;return t=>loginUserDoboard(a,o).then(e=>{if(e.sessionId)localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),localStorage.setItem("spotfix_email",a),spotfixIndexedDB.init();else{if(!("SUCCESS"===e.operationStatus&&e.operationMessage&&0{throw e})}function userUpdate(e,t){var a=localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_user_id"),i=Intl.DateTimeFormat().resolvedOptions().timeZone;return userUpdateDoboard(e,t,a,o,i)}function spotFixSplitUrl(e){try{var t,a,o,i;return e&&""!==e.trim()?(a=(t=new URL(e)).host,0===(o=t.pathname.split("/").filter(Boolean)).length?a:((i=o.reverse()).push(a),i.join(" / "))):""}catch(e){return""}}function setToggleStatus(t){var e=document.getElementById("widget_visibility");e&&(e.checked=!0,e.addEventListener("click",()=>{let e=setTimeout(()=>{localStorage.setItem("spotfix_widget_is_closed","1"),wsSpotfix.close(),t.hide(),clearTimeout(e)},300)}))}function checkLogInOutButtonsVisible(){var e;localStorage.getItem("spotfix_session_id")?(e=document.getElementById("doboard_task_widget-user_menu-signlog_button"))&&(e.style.display="none"):(e=document.getElementById("doboard_task_widget-user_menu-logout_button")?.closest(".doboard_task_widget-user_menu-item"))&&(e.style.display="none")}function changeSize(e){e&&+localStorage.getItem("maximize")?e.classList.add("doboard_task_widget-container-maximize"):e&&e.classList.remove("doboard_task_widget-container-maximize")}let spotFixCSS=`.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:"";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:65px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login span{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active span{margin-bottom:24px}.doboard_task_widget-login span::after{position:absolute;top:0;right:4px;content:"";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active span::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:"";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:"";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:"wght" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:""}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:"";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}`;class CleanTalkWidgetDoboard{selectedText="";selectedData={};widgetElement=null;params={};currentActiveTaskId=0;savedIssuesQuantityOnPage=0;savedIssuesQuantityAll=0;allTasksData={};srcVariables={};constructor(e,t){this.selectedData=e||"",this.selectedText=e?.selectedText||"",this.srcVariables={buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),iconEllipsesMore:SpotFixSVGLoader.getAsDataURI("iconEllipsesMore"),iconPlus:SpotFixSVGLoader.getAsDataURI("iconPlus"),iconMaximize:SpotFixSVGLoader.getAsDataURI("iconMaximize"),chevronBack:SpotFixSVGLoader.getAsDataURI("chevronBack"),buttonPaperClip:SpotFixSVGLoader.getAsDataURI("buttonPaperClip"),buttonSendMessage:SpotFixSVGLoader.getAsDataURI("buttonSendMessage"),logoDoBoardGreen:SpotFixSVGLoader.getAsDataURI("logoDoBoardGreen"),logoDoBoardWrap:SpotFixSVGLoader.getAsDataURI("logoDoBoardWrap"),iconSpotWidgetWrapPencil:SpotFixSVGLoader.getAsDataURI("iconSpotWidgetWrapPencil"),iconMarker:SpotFixSVGLoader.getAsDataURI("iconMarker"),iconSpotPublic:SpotFixSVGLoader.getAsDataURI("iconSpotPublic"),iconSpotPrivate:SpotFixSVGLoader.getAsDataURI("iconSpotPrivate"),iconLinkChain:SpotFixSVGLoader.getAsDataURI("iconLinkChain")},this.fileUploader=new FileUploader(this.escapeHtml),this.init(t)}async init(e){this.params=this.getParams();var t=new URLSearchParams(window.location.search),a=t.get("email_confirmation_token");if(a)try{var o=await confirmUserEmail(a,this.params),i=(this.allTasksData=await getAllTasks(this.params),this.currentActiveTaskId=o.taskId,storageSetWidgetIsClosed(!(e="concrete_issue")),t.delete("email_confirmation_token"),window.location.pathname+(t.toString()?"?"+t.toString():""));window.history.replaceState({},document.title,i)}catch(e){this.registrationShowMessage("Error confirming email: "+e.message,"error")}else{a=localStorage.getItem("spotfix_widget_is_closed");(!a||this.selectedText)&&a||(this.allTasksData=await getAllTasks(this.params))}let s;storageTasksHasUnreadUpdates()?s=!0:"wrap_review"===e&&(s=await checkIfTasksHasSiteOwnerUpdates(this.allTasksData,this.params)),storageSaveTasksUpdateData(this.allTasksData),storageWidgetCloseIsSet()||storageSetWidgetIsClosed(!0),s&&storageSetWidgetIsClosed(!1),this.widgetElement=await this.createWidgetElement(e),this.bindWidgetInputsInteractive()}getParams(){var e=document.querySelector('script[src*="doboard-widget-bundle."]');if(!e||!e.src)throw new Error("Script not provided");e=new URL(e.src),e=Object.fromEntries(e.searchParams.entries());if(!e)throw new Error("Script params not provided");if(e.projectToken&&e.accountId&&e.projectId)return e.accountId&&localStorage.setItem("spotfix_company_id",e.accountId),e.projectToken&&localStorage.setItem("spotfix_project_token",e.projectToken),e;throw new Error("Necessary script params not provided")}bindCreateTaskEvents(){var e=document.getElementById("doboard_task_widget-submit_button");e&&e.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-title"),s=e.value;if(s){var t=document.getElementById("doboard_task_widget-description"),r=t.value;if(r){let t="",a="",o="";var d=document.querySelector(".doboard_task_widget-login");if(d&&d.classList.contains("active")){let e=document.getElementById("doboard_task_widget-user_email");var d=document.getElementById("doboard_task_widget-user_name"),n=document.getElementById("doboard_task_widget-user_password");if(!(a=e.value))return e.style.borderColor="red",e.focus(),void e.addEventListener("input",function(){this.style.borderColor=""});if(e&&d&&!(t=d.value))return d.style.borderColor="red",d.focus(),void d.addEventListener("input",function(){this.style.borderColor=""});if(e&&n&&!d&&!(o=n.value))return n.style.borderColor="red",n.focus(),void n.addEventListener("input",function(){this.style.borderColor=""})}let e=document.getElementById("doboard_task_widget-user_email");a=e.value;d=document.getElementById("doboard_task_widget-submit_button"),n=(d.disabled=!0,d.innerText=ksesFilter("Creating spot..."),{taskTitle:s,taskDescription:r,selectedData:this.selectedData,projectToken:this.params.projectToken,projectId:this.params.projectId,accountId:this.params.accountId,taskMeta:JSON.stringify(this.selectedData||{pageURL:window.location.href})});a&&(n.userEmail=a),t&&(n.userName=t),o&&(n.userPassword=o),localStorage.setItem("spotfix_pending_task",JSON.stringify({...this.selectedData,description:r}));let i;try{i=await this.submitTask(n)}catch(e){return void this.registrationShowMessage(e.message)}d.disabled=!1,d.style.cursor="pointer",i.needToLogin||(void 0!==i.isPublic&&(this.selectedData.isPublic=i.isPublic),this.allTasksData=await getAllTasks(this.params),storageSaveTasksUpdateData(this.allTasksData),this.selectedData={},await this.createWidgetElement("all_issues"),storageSetWidgetIsClosed(!1),hideContainersSpinner(!1))}else t.style.borderColor="red",t.focus(),t.addEventListener("input",function(){this.style.borderColor=""})}else e.style.borderColor="red",e.focus(),e.addEventListener("input",function(){this.style.borderColor=""})})}async createWidgetElement(e,r=!1){var d=document.querySelector(".doboard_task_widget")?document.querySelector(".doboard_task_widget"):document.createElement("div");d.className="doboard_task_widget",d.innerHTML=ksesFilter(""),d.removeAttribute("style");let t="",n,l={};var a=window.SpotfixWidgetConfig;switch(e){case"create_issue":t="create_issue",this.type_name=t,l={selectedText:this.selectedText,currentDomain:document.location.hostname||"",buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),iconMaximize:SpotFixSVGLoader.getAsDataURI("iconMaximize"),iconEllipsesMore:SpotFixSVGLoader.getAsDataURI("iconEllipsesMore"),...this.srcVariables},storageGetUserIsDefined()&&storageSetWidgetIsClosed(!1);break;case"wrap":if(storageGetWidgetIsClosed())return;t="wrap",l={position:Number.isNaN(Number(a?.verticalPosition))?"0vh":Number(a?.verticalPosition)+"vh",...this.srcVariables};break;case"wrap_review":t="wrap_review",l={position:Number.isNaN(Number(a?.verticalPosition))?"0vh":Number(a?.verticalPosition)+"vh",...this.srcVariables};break;case"all_issues":t="all_issues",this.type_name=t,l={...this.srcVariables};break;case"user_menu":t="user_menu";var o=localStorage.getItem("spotfix_app_version")||SPOTFIX_VERSION;l={spotfixVersion:o?"Spotfix version "+o+".":"",avatar:SpotFixSVGLoader.getAsDataURI("iconAvatar"),iconEye:SpotFixSVGLoader.getAsDataURI("iconEye"),iconDoor:SpotFixSVGLoader.getAsDataURI("iconDoor"),chevronBackDark:SpotFixSVGLoader.getAsDataURI("chevronBackDark"),buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),userName:"Guest",email:localStorage.getItem("spotfix_email")||"",...this.srcVariables};break;case"concrete_issue":t="concrete_issue",this.type_name=t,this.savedIssuesQuantityAll=Array.isArray(this.allTasksData)?this.allTasksData.length:0,this.savedIssuesQuantityOnPage=Array.isArray(this.allTasksData)?this.allTasksData.filter(e=>{try{return(e.taskMeta?JSON.parse(e.taskMeta):{}).pageURL===window.location.href}catch(e){return!1}}).length:0,l={issueTitle:"...",issueComments:[],issuesCounter:getIssuesCounterString(this.savedIssuesQuantityOnPage,this.savedIssuesQuantityAll),...this.srcVariables}}d.innerHTML=this.loadTemplate(t,l),document.body.appendChild(d),spotFixRemoveHighlights();var c=document.querySelector(".doboard_task_widget-container");switch(e){case"create_issue":c&&+localStorage.getItem("maximize")?c.classList.add("doboard_task_widget-container-maximize"):c&&c.classList.remove("doboard_task_widget-container-maximize");var g=window.getSelection(),p=!!localStorage.getItem("spotfix_session_id"),u=localStorage.getItem("spotfix_email");p&&u&&!u.includes("spotfix_")&&document.querySelector(".doboard_task_widget-login").classList.add("hidden"),"Range"===g.type&&(spotFixScrollToNodePath(spotFixGetSelectedData(g).nodePath),this.positionWidgetContainer()),this.bindCreateTaskEvents();break;case"wrap":await this.getTaskCount(),document.querySelector(".doboard_task_widget-wrap").addEventListener("click",e=>{e=e.currentTarget.classList;e&&!e.contains("hidden")&&this.createWidgetElement("all_issues")}),hideContainersSpinner(!1);break;case"wrap_review":document.querySelector("#doboard_task_widget_button").addEventListener("click",e=>{spotFixOpenWidget(this.selectedData,"create_issue")});break;case"all_issues":changeSize(c),spotFixRemoveHighlights();let i=0;this.allTasksData?.length||(this.allTasksData=await getAllTasks(this.params));var p=this.allTasksData,_=(n=await getTasksFullDetails(this.params,p,this.currentActiveTaskId),[]);if(0{e=JSON.parse(e.taskMeta).pageURL===a?1:0;return(JSON.parse(t.taskMeta).pageURL===a?1:0)-e});document.querySelector(".doboard_task_widget-all_issues-container").innerHTML="";for(let o=0;oThe issues list is empty')),this.bindIssuesClick(),hideContainersSpinner(!1);break;case"user_menu":setToggleStatus(this),checkLogInOutButtonsVisible();u=await getUserDetails(this.params),g=await getReleaseVersion(),p=localStorage.getItem("spotfix_app_version")||g||SPOTFIX_VERSION;l.spotfixVersion=(p?`Spotfix version ${p}.`:"")||"",u&&(l.userName=u.name||"Guest",l.email=u.email||localStorage.getItem("spotfix_email")||"",u?.avatar?.s)&&(l.avatar=u?.avatar?.s),d.innerHTML=this.loadTemplate("user_menu",l),document.body.appendChild(d),setToggleStatus(this),checkLogInOutButtonsVisible();break;case"concrete_issue":changeSize(c);let a=await getTaskFullDetails(n=await getTasksFullDetails(this.params,this.allTasksData,this.currentActiveTaskId),this.currentActiveTaskId);g=document.querySelector(".doboard_task_widget-issue-title");g&&(g.innerText=ksesFilter(a.issueTitle)),l.issueTitle=a?.issueTitle,l.issueComments=a?.issueComments;let t=null;p=this.allTasksData.find(e=>String(e.taskId)===String(a.taskId));let o=null;if(p&&p.taskMeta)try{o=JSON.parse(p.taskMeta),t=o.nodePath||null}catch(e){t=null,o=null}l.taskPageUrl=o.pageURL;var u=o.pageURL.replace(window.location.origin,""),g=(l.taskFormattedPageUrl=u.length<2?o.pageURL.replace(window.location.protocol+"/",""):u,l.contenerClasess=+localStorage.getItem("maximize")?"doboard_task_widget-container-maximize doboard_task_widget-container":"doboard_task_widget-container",d.innerHTML=this.loadTemplate("concrete_issue",l),document.body.appendChild(d),spotFixRemoveHighlights(),o&&t&&(spotFixHighlightElements([o],this),"function"==typeof spotFixScrollToNodePath)&&spotFixScrollToNodePath(t),document.querySelector(".doboard_task_widget-concrete_issues-container")),v=[],I=localStorage.getItem("spotfix_user_id");if(0e.commentTime.localeCompare(t.commentTime)),E){var D=E[M];e+=this.loadTemplate("concrete_issue_messages",D)}t+=this.loadTemplate("concrete_issue_day_content",{dayContentMonthDay:T,dayContentMessages:e,statusFixedHtml:"DONE"!==n?.taskStatus?"":this.loadTemplate("fixedTaskHtml")})}g.innerHTML=t}else g.innerHTML=ksesFilter("No comments");p=document.querySelector(".doboard_task_widget-send_message_input");function N(){40{var e=document.querySelector(".doboard_task_widget-content");e.scrollTo({top:e.scrollHeight,behavior:"smooth"})},0);let s=document.querySelector(".doboard_task_widget-send_message_button");if(s){this.fileUploader.init();let o=this;s.addEventListener("click",async t=>{t.preventDefault();var t=s.closest(".doboard_task_widget-send_message").querySelector(".doboard_task_widget-send_message_input"),a=t.value.trim();if(a){t.disabled=!0,s.disabled=!0;let e=null;try{e=await addTaskComment(this.params,this.currentActiveTaskId,a),t.value="",await this.createWidgetElement("concrete_issue"),hideContainersSpinner(!1)}catch(e){alert("Error when adding a comment: "+e.message)}o.fileUploader.hasFiles()&&null!==e&&e.hasOwnProperty("commentId")&&(a=localStorage.getItem("spotfix_session_id"),(a=await o.fileUploader.sendAttachmentsForComment(o.params,a,e.commentId)).success||(o.fileUploader.showError("Some files where no sent, see details in the console."),a=JSON.stringify(a),console.log(a))),t.disabled=!1,s.disabled=!1}})}}e=document.querySelector(".doboard_task_widget_return_to_all");let i=this;e&&e.addEventListener("click",function(e,t=i){t.createWidgetElement("all_issues")});e=document.querySelector(".doboard_task_widget-send_message_paperclip");return e&&this.fileUploader.bindPaperClipAction(e),document.querySelector(".doboard_task_widget-close_btn")?.addEventListener("click",e=>{this.hide()}),document.querySelector("#openUserMenuButton")?.addEventListener("click",()=>{this.createWidgetElement("user_menu")}),document.querySelector("#doboard_task_widget-user_menu-logout_button")?.addEventListener("click",()=>{logoutUserDoboard(this.params.projectToken,this.params.accountId).then(()=>{this.hide()})}),document.getElementById("addNewTaskButton")?.addEventListener("click",()=>{spotFixShowWidget()}),document.getElementById("maximizeWidgetContainer")?.addEventListener("click",()=>{var e=document.querySelector(".doboard_task_widget-container");+localStorage.getItem("maximize")&&e.classList.contains("doboard_task_widget-container-maximize")?(localStorage.setItem("maximize","0"),e.classList.remove("doboard_task_widget-container-maximize")):(localStorage.setItem("maximize","1"),e.classList.add("doboard_task_widget-container-maximize"))}),document.querySelector("#doboard_task_widget-user_menu-signlog_button")?.addEventListener("click",()=>{spotFixShowWidget()}),document.querySelector("#spotfix_back_button")?.addEventListener("click",()=>{this.createWidgetElement(this.type_name)}),d}bindIssuesClick(){document.querySelectorAll(".issue-item").forEach(e=>{e.addEventListener("click",async()=>{let t=null;try{t=JSON.parse(e.getAttribute("data-node-path"))}catch(e){t=null}t&&spotFixScrollToNodePath(t),this.currentActiveTaskId=e.getAttribute("data-task-id"),await this.showOneTask()})})}async showOneTask(){await this.createWidgetElement("concrete_issue");var e=this.getTaskHighlightData(this.currentActiveTaskId);e&&(spotFixRemoveHighlights(),spotFixHighlightElements([e],this),this.positionWidgetContainer()),hideContainersSpinner(!1)}loadTemplate(t,e={}){let a=SpotFixTemplatesLoader.getTemplateCode(t);for(var[o,i]of Object.entries(e)){o=`{{${o}}}`;let e;e=this.isPlaceholderInAttribute(a,o)?this.escapeHtml(String(i)):ksesFilter(String(i),{template:t,imgFilter:!0}),a=a.replaceAll(o,e)}return ksesFilter(a,{template:t})}isPlaceholderInAttribute(e,t){t=t.replace(/[{}]/g,"\\$&");return new RegExp(`[\\w-]+\\s*=\\s*["'][^"']*${t}[^"']*["']`,"g").test(e)}escapeHtml=e=>e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'");async getTaskCount(){if(!localStorage.getItem("spotfix_session_id"))return{};var e=this.params.projectToken,t=localStorage.getItem("spotfix_session_id"),a=localStorage.getItem("spotfix_tasks_count");let o;o=0===a||a?a:(await getTasksDoboard(e,t,this.params.accountId,this.params.projectId),(await spotfixIndexedDB.getAll(TABLE_TASKS)).filter(e=>e.taskMeta).length);a=document.getElementById("doboard_task_widget-task_count");a&&(a.innerText=ksesFilter(o),a.classList.remove("hidden"))}async submitTask(e){localStorage.getItem("spotfix_session_id")||(await registerUser(e)(this.registrationShowMessage),e.userPassword&&await loginUser(e)(this.registrationShowMessage));var t=localStorage.getItem("spotfix_session_id");return t?handleCreateTask(t,e):{needToLogin:!0}}hide(){spotFixRemoveHighlights(),this.createWidgetElement("wrap")}wrapElementWithSpotfixHighlight(e){var t=e.cloneNode(),a=document.createElement("span");return a.className="doboard_task_widget-text_selection image-highlight",e.insertAdjacentElement("beforebegin",a),a.appendChild(t),a}getTaskHighlightData(t){var e=this.allTasksData.find(e=>e.taskId.toString()===t.toString());if(e&&void 0!==e.taskMeta){let t=null;try{t=JSON.parse(e.taskMeta)}catch(e){t=null}if(null!==t&&"object"==typeof t)return t}return null}bindWidgetInputsInteractive(){document.querySelectorAll(".doboard_task_widget-field").forEach(e=>{e.value&&e.classList.add("has-value"),e.addEventListener("input",()=>{e.value?e.classList.add("has-value"):e.classList.remove("has-value")}),e.addEventListener("blur",()=>{e.value||e.classList.remove("has-value")})});var t=document.querySelector(".doboard_task_widget-login span");if(t){let e=this;t.addEventListener("click",function(){this.closest(".doboard_task_widget-login").classList.toggle("active"),e.positionWidgetContainer(),setTimeout(()=>{var e=document.querySelector(".doboard_task_widget-content");e.scrollTo({top:e.scrollHeight,behavior:"smooth"})},0)})}window.addEventListener("scroll",this.handleScroll.bind(this)),window.addEventListener("resize",this.handleResize.bind(this))}registrationShowMessage(e,t="error"){var a=document.getElementById("doboard_task_widget-error_message-header"),o=document.getElementById("doboard_task_widget-error_message"),i=document.querySelector(".doboard_task_widget-message-wrapper");"string"==typeof e&&null!==o&&null!==i&&(o.innerText=ksesFilter(e),i.classList.remove("hidden"),o.classList.remove("doboard_task_widget-notice_message","doboard_task_widget-error_message"),"notice"===t?(a.innerText=ksesFilter(""),i.classList.add("doboard_task_widget-notice_message"),o.style.color="#2a5db0"):(a.innerText=ksesFilter("Registration error"),i.classList.add("doboard_task_widget-error_message"),o.style.color="red"))}positionWidgetContainer(){var t=document.querySelector(".doboard_task_widget-text_selection"),a=document.querySelector(".doboard_task_widget"),o=document.querySelector(".doboard_task_widget-content.doboard_task_widget-create_issue"),i=document.querySelector(".doboard_task_widget-concrete_issues-container");if((o||i)&&t){var o=window.scrollY,i=window.innerHeight,t=t.getBoundingClientRect().top+o,s=a.offsetHeight;let e;t-o<0?e=10:(i{this.positionWidgetContainer()},10)}handleResize(){clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(()=>{this.positionWidgetContainer()},100)}isSpotHaveToBeHighlighted(e){return!0}sanitizeNodePath(e){e=Array.isArray(e)?JSON.stringify(e):String(e);return/^[\[\]0-9,\s]*$/.test(e)?e:""}}var spotFixShowDelayTimeout=null;let SPOTFIX_DEBUG=!1,SPOTFIX_SHOW_DELAY=1e3;function spotFixInit(){spotfixIndexedDB.init(),wsSpotfix.connect(),wsSpotfix.subscribe(),new SpotFixSourcesLoader,new CleanTalkWidgetDoboard({},"wrap"),loadBotDetector()}function loadBotDetector(){var e;document.querySelector('script[src="https://moderate.cleantalk.org/ct-bot-detector-wrapper.js"]')||document.getElementById("ct-bot-detector-script")||((e=document.createElement("script")).src="https://moderate.cleantalk.org/ct-bot-detector-wrapper.js",e.async=!0,e.id="ct-bot-detector-script",document.head.appendChild(e))}function spotFixShowWidget(){new CleanTalkWidgetDoboard(null,"create_issue")}function spotFixIsInsideWidget(t){if(t){let e=t.nodeType===Node.ELEMENT_NODE?t:t.parentElement;for(;e;){if(e.classList&&e.classList.contains("doboard_task_widget"))return!0;e=e.parentElement}}return!1}function spotFixOpenWidget(e,t){e&&new CleanTalkWidgetDoboard(e,t)}function spotFixDebugLog(e){SPOTFIX_DEBUG&&console.log(e)}function hideContainersSpinner(){var t=document.getElementsByClassName("doboard_task_widget-spinner_wrapper_for_containers");if(0e?.taskId?.toString()===t?.toString());let i=e.users,o=0String(e.user_id)===String(o.userId))),"");o&&((e=formatDate(o.commentDate)).date,r=e.time);var e=getAvatarSrc(s),d=getAuthorName(s);return{taskId:t,taskAuthorAvatarImgSrc:e,taskAuthorName:d,lastMessageText:o?o.commentBody:"No messages yet",lastMessageTime:r,issueTitle:0new Date(e.commentDate)-new Date(t.commentDate)).map(t=>{var{date:e,time:a}=formatDate(t.commentDate);let o=null;return{commentAuthorAvatarSrc:getAvatarSrc(o=i&&0String(e.user_id)===String(t.userId)):o),commentAuthorName:getAuthorName(o),commentBody:t.commentBody,commentDate:e,commentTime:a,commentUserId:t.userId||"Unknown User"}})}}function getAvatarData(e){let t,a;var o=e.taskAuthorName&&"Anonymous"!=e.taskAuthorName?e.taskAuthorName.trim().charAt(0).toUpperCase():null;let i="doboard_task_widget-avatar-initials";return null===e.taskAuthorAvatarImgSrc&&null!==o&&(t="display: flex;background-color: #f8de7e;justify-content: center;align-items: center;",a="doboard_task_widget-avatar_container"),null===e.taskAuthorAvatarImgSrc&&null===o&&(t="background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAE9GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4wLWMwMDAgNzkuMTcxYzI3ZmFiLCAyMDIyLzA4LzE2LTIyOjM1OjQxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjQuMCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjQtMDQtMTBUMTk6MDg6MDkrMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxNWRjOWI0Yy04ZWVmLTRkNTEtYmE0MS1kOTkzZTZmNjNmMTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTVkYzliNGMt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');",a="doboard_task_widget-avatar_container",i+=" doboard_task_widget-hidden_element"),null!==e.taskAuthorAvatarImgSrc&&(t=`background-image:url('${e.taskAuthorAvatarImgSrc}');`,a="doboard_task_widget-avatar_container",i="doboard_task_widget-hidden_element"),{avatarStyle:t,avatarCSSClass:a,taskAuthorInitials:o,initialsClass:i}}function isAnyTaskUpdated(t){var a=[];for(let e=0;e{var t=e.name.toLowerCase();l[a]?.includes(t)&&!t.startsWith("on")&&!e.value.toLowerCase().includes("javascript:")||o.removeAttribute(e.name)})}[...o.childNodes].forEach(e)}),c.body.innerHTML}"loading"!==document.readyState?document.addEventListener("spotFixLoaded",spotFixInit):document.addEventListener("DOMContentLoaded",spotFixInit),document.addEventListener("selectionchange",function(e){var t;e.target===document&&(e=!!document.getElementsByClassName("wrap_review")[0],(t=document.getSelection())&&""!==t.toString()||!e?(spotFixShowDelayTimeout&&clearTimeout(spotFixShowDelayTimeout),spotFixShowDelayTimeout=setTimeout(()=>{var e,t,a=window.getSelection();"Range"===a.type&&(t=a.anchorNode,e=a.focusNode,spotFixIsInsideWidget(t)||spotFixIsInsideWidget(e)||(t=spotFixGetSelectedData(a))&&spotFixOpenWidget(t,"wrap_review"))},SPOTFIX_SHOW_DELAY)):new CleanTalkWidgetDoboard({},"wrap"))});let SPOTFIX_SELECTION_TYPE_TEXT="text",SPOTFIX_SELECTION_TYPE_IMG="image",SPOTFIX_SELECTION_TYPE_ELEMENT="element";function spotFixGetSelectionType(e){var t=e.getRangeAt(0),a=t.commonAncestorContainer;return spotFixGetSelectedImage(e)?SPOTFIX_SELECTION_TYPE_IMG:a.nodeType===Node.ELEMENT_NODE&&1s&&(s=o.length),r=spotFixCalculateNodePath(n);break;case SPOTFIX_SELECTION_TYPE_IMG:var n=t.startContainer,l=spotFixGetSelectedImage(e);o=`Image (${l.alt||"no description"})`,r=spotFixCalculateNodePath(l),i=Array.from(n.parentNode.children).indexOf(n),s=i+1;break;case SPOTFIX_SELECTION_TYPE_ELEMENT:l=d.nodeType===Node.ELEMENT_NODE?d:d.parentElement;if(l.childNodes.length<=1)return spotFixDebugLog("`spotFixGetSelectedData` skip by `Selection have not inner data`"),null;o=l.textContent||"",r=spotFixCalculateNodePath(l),i=Array.from(l.parentNode.children).indexOf(l),s=i+1}var c=window.location.href;return{startSelectPosition:i,endSelectPosition:s,selectedText:o.trim(),pageURL:c,nodePath:r,selectionType:a,imageUrl:(SPOTFIX_SELECTION_TYPE_IMG,"")}}function spotFixHighlightElements(e,o){if(0!==e.length){let a=new Map;e.forEach(e=>{var t;e?.nodePath&&Array.isArray(e?.nodePath)?this.spotFixIsValidNodePath(e.nodePath)?(t=spotFixRetrieveNodeFromPath(e.nodePath))?e.selectionType?e.selectionType&&![SPOTFIX_SELECTION_TYPE_TEXT,SPOTFIX_SELECTION_TYPE_IMG,SPOTFIX_SELECTION_TYPE_ELEMENT].includes(e.selectionType)?spotFixDebugLog("Invalid selection type: "+e.selectionType):(a.has(t)||a.set(t,[]),a.get(t).push(e)):spotFixDebugLog("Selection type is not provided."):spotFixDebugLog("Element not found for path: "+e.nodePath):spotFixDebugLog("Invalid nodePath format: "+e.nodePath):spotFixDebugLog("Invalid spot: missing or invalid nodePath: "+e)}),a.forEach((e,t)=>{var a=e[0].selectionType;switch(a){case"image":this.spotFixHighlightImageElement(t);break;case"element":this.spotFixHighlightNestedElement(t);break;case"text":this.spotFixHighlightTextInElement(t,e,o);break;default:spotFixDebugLog("Unknown selection type: "+a)}})}}function spotFixHighlightImageElement(e){"IMG"!==e.tagName?spotFixDebugLog("Expected IMG element for image highlight, got: "+e.tagName):e.classList.add("doboard_task_widget-image_selection")}function spotFixHighlightNestedElement(e){e.classList.add("doboard_task_widget-element_selection")}function spotFixHighlightTextInElement(e,t,i){let a="";let s=`${`
+let INDEXED_DB_NAME="spotfix-localDB",indexedDBVersion=1,TABLE_USERS="users",TABLE_TASKS="tasks",TABLE_COMMENTS="comments",LOCAL_DATA_BASE_TABLE=[{name:TABLE_USERS,keyPath:"user_id"},{name:TABLE_TASKS,keyPath:"taskId"},{name:TABLE_COMMENTS,keyPath:"commentId"}];async function openIndexedDB(o,i=indexedDBVersion){return new Promise((t,e)=>{let a=indexedDB.open(o,i);a.onsuccess=()=>t(a.result),a.onerror=()=>e(a.error),a.onupgradeneeded=e=>t(a.result)})}async function deleteDB(){try{for(let a of await window.indexedDB.databases())await new Promise(e=>{var t=indexedDB.deleteDatabase(a.name);t.onsuccess=()=>e(),t.onerror=()=>e()})}catch(e){console.warn("deleteDB error",e)}}let spotfixIndexedDB={getIndexedDBName:()=>INDEXED_DB_NAME+"_"+(localStorage.getItem("spotfix_session_id")||localStorage.getItem("spotfix_project_token")),error:(e,t)=>{console.error("IndexedDB error",e,t)},init:async()=>{var e=localStorage.getItem("spotfix_session_id"),t=localStorage.getItem("spotfix_project_token");if(!e&&!t)return{needInit:!1};let s=spotfixIndexedDB.getIndexedDBName();return await deleteDB(),new Promise((i,a)=>{var e=indexedDB.open(s,indexedDBVersion);e.onupgradeneeded=e=>{let a=e.target.result;LOCAL_DATA_BASE_TABLE.forEach(e=>{var t;a.objectStoreNames.contains(e.name)||(t=a.createObjectStore(e.name,{keyPath:e.keyPath}),e.name===TABLE_COMMENTS&&t.createIndex("taskId","taskId"),e.name===TABLE_TASKS&&t.createIndex("userId","userId"))}),i({needInit:!0})},e.onsuccess=e=>{let t=e.target.result,o=LOCAL_DATA_BASE_TABLE.filter(e=>!t.objectStoreNames.contains(e.name));0===o.length?(t.close(),i({needInit:!0})):(e=t.version+1,t.close(),(e=indexedDB.open(s,e)).onupgradeneeded=e=>{let a=e.target.result;o.forEach(e=>{var t=a.createObjectStore(e.name,{keyPath:e.keyPath});e.name===TABLE_COMMENTS&&t.createIndex("taskId","taskId"),e.name===TABLE_TASKS&&t.createIndex("userId","userId")})},e.onsuccess=()=>i({needInit:!0}),e.onerror=e=>a(e))},e.onerror=e=>a(e)})},withStore:async(s,r="readwrite",d)=>{let n=await openIndexedDB(spotfixIndexedDB.getIndexedDBName(),indexedDBVersion);return new Promise((t,a)=>{try{var o=n.transaction(s,r),i=o.objectStore(s);let e=d(i);o.oncomplete=()=>{n.close(),t(e)},o.onerror=e=>{n.close(),a(e.target.error)}}catch(e){n.close(),a(e)}})},put:async(e,a)=>spotfixIndexedDB.withStore(e,"readwrite",t=>{Array.isArray(a)?a.forEach(e=>t.put(e)):t.put(a)}),delete:async(e,t)=>spotfixIndexedDB.withStore(e,"readwrite",e=>{e.delete(t)}),clearTable:async e=>spotfixIndexedDB.withStore(e,"readwrite",e=>e.clear()),clearPut:async(e,t)=>{await spotfixIndexedDB.clearTable(e),await spotfixIndexedDB.put(e,t)},getAll:async(e,i,s)=>spotfixIndexedDB.withStore(e,"readonly",o=>new Promise((e,t)=>{let a;(a=i&&void 0!==s?o.index(i).getAll(s):o.getAll()).onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})),getTable:async e=>localStorage.getItem("spotfix_session_id")||localStorage.getItem("spotfix_project_token")?spotfixIndexedDB.getAll(e):[],deleteTable:async(e,t)=>spotfixIndexedDB.delete(e,t)},SPOTFIX_DOBOARD_API_URL="https://api.doboard.com",spotfixApiCall=async(e,t,a=void 0)=>{if(!e||"object"!=typeof e)throw new Error("Data must be a valid object");if(!t||"string"!=typeof t)throw new Error("Method must be a valid string");if(void 0!==a&&"string"!=typeof a&&"number"!=typeof a)throw new Error("AccountId must be a string or number");var o,i=new FormData;for(o in e)e.hasOwnProperty(o)&&null!=e[o]&&i.append(o,e[o]);let s;s=void 0!==a?SPOTFIX_DOBOARD_API_URL+`/${a}/`+t:SPOTFIX_DOBOARD_API_URL+"/"+t;try{new URL(s)}catch(e){throw new Error("Invalid endpoint URL: "+s)}let r;try{r=await fetch(s,{method:"POST",body:i})}catch(e){throw new Error("Network error: "+e.message)}let d;try{d=await r.json()}catch(e){throw new Error("Failed to parse JSON response from server")}if(!d||"object"!=typeof d)throw new Error("Invalid response format from server");if(!d.data)throw new Error("Missing data field in server response");if(!d.data.operation_status)throw new Error("Missing operation_status in response data");if("FAILED"===d.data.operation_status)throw a=d.data.operation_message||"Operation failed without specific message","session_id Unknown"===d?.data?.operation_message&&(clearLocalstorageOnLogout(),checkLogInOutButtonsVisible(),await deleteDB()),new Error(a);if("SUCCESS"===d.data.operation_status)return d.data;throw new Error("Unknown operation status: "+d.data.operation_status)},userConfirmEmailDoboard=async e=>{e={email_confirmation_token:encodeURIComponent(e)},e=await spotfixApiCall(e,"user_confirm_email");return{sessionId:e.session_id,userId:e.user_id,email:e.email,accounts:e.accounts,operationStatus:e.operation_status}},createTaskDoboard=async(e,t)=>{var a=t.accountId,e={session_id:e,project_token:t.projectToken,project_id:t.projectId,user_id:localStorage.getItem("spotfix_user_id"),name:t.taskTitle,comment:t.taskDescription,meta:t.taskMeta,task_type:"PUBLIC"};return{taskId:(await spotfixApiCall(e,"task_add",a)).task_id}},createTaskCommentDoboard=async(e,t,a,o,i,s="ACTIVE")=>{t={session_id:t,project_token:i,task_id:a,comment:o,status:s};return{commentId:(await spotfixApiCall(t,"comment_add",e)).comment_id}},attachmentAddDoboard=async e=>{var t=e.params.accountId,e={session_id:e.sessionId,project_token:e.params.projectToken,account_id:e.params.accountId,comment_id:e.commentId,filename:e.fileName,file:e.fileBinary,attachment_order:e.attachmentOrder};await spotfixApiCall(e,"attachment_add",t)},registerUserDoboard=async(t,e,a,o,i)=>{t={project_token:t,account_id:e,confirmation_url:a};if(a&&o&&(t.email=a,t.name=o),localStorage.getItem("bot_detector_event_token"))try{var s=JSON.parse(localStorage.getItem("bot_detector_event_token"));s?.value&&(t.bot_detector_event_token=s?.value)}catch(e){t.bot_detector_event_token=""}e=await spotfixApiCall(t,"user_registration");return{sessionId:e.session_id,userId:e.user_id,email:e.email,accountExists:1===e.user_email_confirmed,operationMessage:e.operation_message,operationStatus:e.operation_status,userEmailConfirmed:e.user_email_confirmed,accounts:e.accounts}},loginUserDoboard=async(e,t)=>{e={email:e,password:t},t=await spotfixApiCall(e,"user_authorize");return{sessionId:t.session_id,userId:t.user_id,email:t.email,accountExists:1===t.user_email_confirmed,operationMessage:t.operation_message,operationStatus:t.operation_status,userEmailConfirmed:t.user_email_confirmed,accounts:t.accounts}},forgotPasswordDoboard=async e=>{e={email:e};return spotfixApiCall(e,"user_password_reset")},logoutUserDoboard=async e=>{var t,a=localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_accounts"),o="undefined"!==o?JSON.parse(o||"[]"):[],o=0
{t={session_id:t,project_token:e,project_id:o,task_type:"PUBLIC",status:"ACTIVE,DONE"};i&&(t.user_id=i);e=(await spotfixApiCall(t,"task_get",a)).tasks.map(e=>({taskId:e.task_id,taskTitle:e.name,userId:e.user_id,taskLastUpdate:e.updated,taskCreated:e.created,taskCreatorTaskUser:e.creator_user_id,taskMeta:e.meta,taskStatus:e.status}));return await spotfixIndexedDB.clearPut(TABLE_TASKS,e),storageSaveTasksCount(e),e},getTasksCommentsDoboard=async(e,t,a,o="ACTIVE")=>{e={session_id:e,project_token:a,status:o},a=(await spotfixApiCall(e,"comment_get",t)).comments.map(e=>({taskId:e.task_id,commentId:e.comment_id,userId:e.user_id,commentBody:e.comment,commentDate:e.updated,status:e.status,issueTitle:e.task_name}));return await spotfixIndexedDB.clearPut(TABLE_COMMENTS,a),a},getUserDoboard=async(e,t,a,o)=>{e={session_id:e,project_token:t},o&&(e.user_id=o),t=await spotfixApiCall(e,"user_get",a);return e.user_id?await spotfixIndexedDB.put(TABLE_USERS,t.users):await spotfixIndexedDB.clearPut(TABLE_USERS,t.users),t.users},userUpdateDoboard=async(e,t,a,o,i)=>{a={session_id:a,project_token:e,user_id:o,timestamp:i};return await spotfixApiCall(a,"user_update",t),{success:!0}},getReleaseVersion=async()=>{try{var e=await(await fetch("https://api.github.com/repos/CleanTalk/SpotFix/releases")).json();return 0localStorage.getItem("spotfix_session_id"),buildMessage=e=>({channel:"account:"+localStorage.getItem("spotfix_company_id"),action:e,account_id:localStorage.getItem("spotfix_company_id"),session_id:getSessionId(),project_token:localStorage.getItem("spotfix_project_token")}),wsSpotfix={connect(){socket&&socket.readyState===WebSocket.OPEN||!getSessionId()||((socket=new WebSocket(WS_URL)).onopen=()=>{heartbeatInterval=setInterval(()=>{socket?.readyState===WebSocket.OPEN&&socket.send("heartbeat")},5e4),wsSpotfix.send(buildMessage("SUBSCRIBE"))},socket.onmessage=t=>{if("heartbeat"!==t.data)try{var e=JSON.parse(t.data);switch(e.object){case"users":spotfixIndexedDB.put(TABLE_USERS,e.data);break;case"tasks":"REMOVED"===e.data.status?spotfixIndexedDB.delete(TABLE_TASKS,e.data.task_id):spotfixIndexedDB.put(TABLE_TASKS,{taskId:e.data.task_id,taskTitle:e.data.name,userId:e.data.user_id,taskLastUpdate:e.data.updated,taskCreated:e.data.created,taskCreatorTaskUser:e.data.creator_user_id,taskMeta:e.data.meta,taskStatus:e.data.status});break;case"comments":"REMOVED"===e.data.status?spotfixIndexedDB.delete(TABLE_COMMENTS,e.data.comment_id):spotfixIndexedDB.put(TABLE_COMMENTS,{taskId:e.data.task_id,commentId:e.data.comment_id,userId:e.data.user_id,commentBody:e.data.comment,commentDate:e.data.updated,status:e.data.status,issueTitle:e.data.task_name})}}catch(e){console.warn("WS non-JSON message:",t.data)}},socket.onclose=e=>{console.warn("WS closed:",e.code,e.reason),socket=null,heartbeatInterval&&(clearInterval(heartbeatInterval),heartbeatInterval=null)},socket.onerror=e=>{console.error("WS error:",e)})},send(e){socket&&socket.readyState===WebSocket.OPEN?socket.send(JSON.stringify(e)):console.warn("WebSocket is not connected")},close(){wsSpotfix.unsubscribe(),socket?.close()},subscribe(){socket?.readyState===WebSocket.OPEN&&wsSpotfix.send(buildMessage("SUBSCRIBE"))},unsubscribe(){socket?.readyState===WebSocket.OPEN&&wsSpotfix.send(buildMessage("UNSUBSCRIBE"))}},SPOTFIX_VERSION="1.1.5",spotFixCSS=`.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:"";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:40px;margin-top:10px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-hidden,.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login .doboard_task_widget-login-icon{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active .doboard_task_widget-login-icon{margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-login-icon::after{position:absolute;top:0;right:4px;content:"";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-login-icon::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{min-height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-login-buttons-wrapper{display:flex;gap:10px;margin-bottom:10px}.doboard_task_widget-login-buttons-wrapper .doboard_task_widget-submit_button{margin-bottom:0;width:auto;min-height:32px;font-size:14px;padding:4px 12px}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page{flex:1;background:#FFF;border:1px solid #22A475;color:#22A475}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black:hover,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page:hover{background:#f0fdf4;color:#1C7857}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-login_button,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-restore_password_button{flex:2}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:"";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:"";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:"wght" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:""}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:"";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.doboard_task_widget-bottom-eye-icon,.doboard_task_widget-bottom-eye-off-icon{position:absolute;right:10px;top:50%;transform:translateY(-50%);width:20px;height:20px;cursor:pointer;border-radius:50%;transition:all .2s ease;z-index:10}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}.doboard_task_widget-forgot_password,.doboard_task_widget-on_phantom_login_page,.doboard_task_widget-show_login_form{display:inline-block;cursor:pointer;color:#2F68B7;margin-bottom:0}.doboard_task_widget-forgot_password{margin-bottom:20px}.doboard_task_widget-login-is-invalid{color:red}.doboard_task_widget-forgot_password_form-menu,.doboard_task_widget-input-container-login-menu{margin:20px}.doboard_task_widget-bottom-eye-icon{background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMjAgMjAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDIwIDIwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBkPSJNMTAsMTcuNGMtNi4yLDAtOS43LTYuOC05LjgtNy4xYy0wLjEtMC4yLTAuMS0wLjUsMC0wLjdDMC4zLDkuNCwzLjgsMi42LDEwLDIuNmM2LjIsMCw5LjcsNi44LDkuOCw3LjENCgljMC4xLDAuMiwwLjEsMC41LDAsMC43QzE5LjcsMTAuNiwxNi4yLDE3LjQsMTAsMTcuNHogTTEuNywxMGMwLjgsMS4zLDMuNyw1LjksOC4zLDUuOWM0LjYsMCw3LjYtNC42LDguMy01LjkNCgljLTAuOC0xLjMtMy43LTUuOS04LjMtNS45QzUuNCw0LjEsMi40LDguNywxLjcsMTB6IE0xMCwxMy4zYy0xLjgsMC0zLjMtMS41LTMuMy0zLjNTOC4yLDYuOCwxMCw2LjhzMy4zLDEuNSwzLjMsMy4zDQoJUzExLjgsMTMuMywxMCwxMy4zeiBNMTAsOC4zQzksOC4zLDguMyw5LDguMywxMFM5LDExLjgsMTAsMTEuOHMxLjgtMC44LDEuOC0xLjhTMTEsOC4zLDEwLDguM3oiLz4NCjwvc3ZnPg0K) center center no-repeat #fff;background-size:16px 16px}.doboard_task_widget-bottom-eye-off-icon{background:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDIwIDIwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyMCAyMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE2LjgsMTMuMmMwLjEsMC4xLDAuMywwLjIsMC41LDAuMmMwLDAsMCwwLDAsMGMwLjIsMCwwLjQtMC4xLDAuNS0wLjNjMC43LTAuOSwxLjQtMS44LDEuOS0yLjgNCgljMC4xLTAuMiwwLjEtMC41LDAtMC43Yy0wLjEtMC4zLTMuNi03LjEtOS44LTcuMWMwLDAsMCwwLDAsMGMtMC42LDAtMS4zLDAuMS0xLjksMC4yQzcuOCwyLjksNy42LDMuMSw3LjUsMy4zczAsMC41LDAuMiwwLjcNCglMMTYuOCwxMy4yeiBNMTAsNC4xYzQuNiwwLDcuNiw0LjYsOC4zLDUuOWMtMC4zLDAuNS0wLjYsMS0xLDEuNUw5LjksNC4xQzkuOSw0LjEsMTAsNC4xLDEwLDQuMXogTTE5LjcsMTguNmwtNC4yLTQuMkw1LjYsNC41DQoJYzAsMCwwLDAsMCwwTDEuNCwwLjNDMS4xLDAsMC42LDAsMC4zLDAuM1MwLDEuMSwwLjMsMS40TDMuOSw1QzIuNCw2LjMsMS4xLDcuOSwwLjIsOS42Yy0wLjEsMC4yLTAuMSwwLjUsMCwwLjcNCgljMC4xLDAuMywzLjYsNy4xLDkuOSw3LjFjMS43LDAsMy40LTAuNSw0LjktMS41bDMuOCwzLjhjMC4xLDAuMSwwLjMsMC4yLDAuNSwwLjJzMC40LTAuMSwwLjUtMC4yQzIwLDE5LjQsMjAsMTguOSwxOS43LDE4LjZ6DQoJIE04LjMsOS40bDIuMywyLjNjLTAuMiwwLjEtMC40LDAuMS0wLjYsMC4xYy0wLjIsMC0wLjUsMC0wLjctMC4xYy0wLjItMC4xLTAuNC0wLjItMC42LTAuNGMtMC4yLTAuMi0wLjMtMC40LTAuNC0wLjYNCgljLTAuMS0wLjItMC4xLTAuNS0wLjEtMC43QzguMiw5LjgsOC4yLDkuNiw4LjMsOS40eiBNMTAsMTUuOWMtNC42LDAtNy42LTQuNi04LjMtNS45YzAuOS0xLjUsMi0yLjgsMy4zLTMuOWwyLjIsMi4yDQoJQzcuMSw4LjQsNyw4LjYsNyw4LjdDNi44LDkuMSw2LjcsOS42LDYuNywxMGMwLDAuNCwwLjEsMC45LDAuMiwxLjNjMC4yLDAuNCwwLjQsMC44LDAuNywxLjFjMC4zLDAuMywwLjcsMC42LDEuMSwwLjcNCgljMC40LDAuMiwwLjgsMC4yLDEuMywwLjJjMC40LDAsMC45LTAuMSwxLjMtMC4zYzAuMi0wLjEsMC4zLTAuMiwwLjUtMC4zbDIuMSwyLjFDMTIuNiwxNS41LDExLjMsMTUuOSwxMCwxNS45eiIvPg0KPC9zdmc+DQo=) center center no-repeat #fff;background-size:16px 16px;opacity:.5}`;async function confirmUserEmail(e,t){var e=await userConfirmEmailDoboard(e),a=(localStorage.setItem("spotfix_email",e.email),localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),await spotfixIndexedDB.init(),localStorage.getItem("spotfix_pending_task"));if(!a)throw new Error("No pending task data");let o;try{o=JSON.parse(a)}catch(e){throw new Error("Invalid pending task data")}a={taskTitle:o.selectedText||"New Task",taskDescription:o.description||"",selectedData:o,projectToken:t.projectToken,projectId:t.projectId,accountId:t.accountId,taskMeta:JSON.stringify(o)},t=await handleCreateTask(e.sessionId,a);return localStorage.removeItem("spotfix_pending_task"),t}async function getTasksFullDetails(e,t,a){var o,i;if(0+e.taskId==+a)?.taskStatus}}async function getUserDetails(e){var t=localStorage.getItem("spotfix_session_id");let a=localStorage.getItem("spotfix_user_id");if(a)return await getUserDoboard(t,e.projectToken,e.accountId,a),(await spotfixIndexedDB.getAll(TABLE_USERS)).find(e=>+e.user_id==+a)||{}}async function handleCreateTask(e,t){try{var a,o=await createTaskDoboard(e,t);return o&&o.taskId&&t.taskDescription&&(a=`The spot has been posted at the following URL ${window.location.href} `,await addTaskComment({projectToken:t.projectToken,accountId:t.accountId},o.taskId,t.taskDescription+a)),o}catch(e){throw e}}async function addTaskComment(e,t,a){var o=localStorage.getItem("spotfix_session_id");if(!o)throw new Error("No session");if(e.projectToken&&e.accountId)return createTaskCommentDoboard(e.accountId,o,t,a,e.projectToken);throw new Error("Missing params")}async function getUserTasks(e){var t,a,o;return localStorage.getItem("spotfix_session_id")?(t=e.projectToken,a=localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_user_id"),await getTasksDoboard(t,a,e.accountId,e.projectId,o),spotfixIndexedDB.getAll(TABLE_TASKS,"userId",o)):{}}async function getAllTasks(e){var t,a;return localStorage.getItem("spotfix_session_id")?(t=e.projectToken,a=localStorage.getItem("spotfix_session_id"),await getTasksDoboard(t,a,e.accountId,e.projectId),(await spotfixIndexedDB.getAll(TABLE_TASKS)).filter(e=>e.taskMeta)):{}}function formatDate(e){if(!e)return{date:"",time:""};let t;return t=!e.includes("T")&&e.includes(" ")?new Date(e.replace(" ","T")):new Date(e),isNaN(t.getTime())?{date:"",time:""}:(e=t.getTimezoneOffset(),{date:["January","February","March","April","May","June","July","August","September","October","November","December"][(e=new Date(t.getTime()-6e4*e)).getMonth()]+" "+e.getDate(),time:e.getHours().toString().padStart(2,"0")+":"+e.getMinutes().toString().padStart(2,"0")})}function getTaskAuthorDetails(e,t){localStorage.getItem("spotfix_session_id");var a=[{taskId:"1",taskAuthorAvatarImgSrc:"https://s3.eu-central-1.amazonaws.com/cleantalk-ctask-atts/accounts/1/avatars/081a1b65d20fe318/m.jpg",taskAuthorName:"Test All Issues Single Author Name"}].find(e=>e.taskId===t);return void 0===a?{taskId:null,taskAuthorAvatarImgSrc:null,taskAuthorName:"Task Author"}:a}function getIssuesCounterString(e,t){return` (${e}/${t})`}function getAvatarSrc(e){if(e&&e.avatar){if("object"==typeof e.avatar&&e.avatar.m)return e.avatar.m;if("string"==typeof e.avatar)return e.avatar}return null}function getAuthorName(e){if(e){if(e.name&&0registerUserDoboard(i,s,a,o,r).then(e=>{if(e.accountExists)document.querySelector(".doboard_task_widget-accordion>.doboard_task_widget-input-container").innerText=ksesFilter("Account already exists. Please, login usin your password."),document.querySelector(".doboard_task_widget-accordion>.doboard_task_widget-input-container.hidden").classList.remove("hidden"),document.getElementById("doboard_task_widget-user_password").focus();else if(e.sessionId)localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),localStorage.setItem("spotfix_email",e.email),localStorage.setItem("spotfix_accounts",JSON.stringify(e.accounts)),spotfixIndexedDB.init(),userUpdate(i,s);else{if(!("SUCCESS"===e.operationStatus&&e.operationMessage&&0{throw e})}function loginUser(e){let a=e.userEmail,o=e.userPassword;return t=>loginUserDoboard(a,o).then(e=>{if(e.sessionId)localStorage.setItem("spotfix_session_id",e.sessionId),localStorage.setItem("spotfix_user_id",e.userId),localStorage.setItem("spotfix_email",e.email),localStorage.setItem("spotfix_email",a),localStorage.setItem("spotfix_accounts",JSON.stringify(e.accounts)),checkLogInOutButtonsVisible(),spotfixIndexedDB.init();else{if(!("SUCCESS"===e.operationStatus&&e.operationMessage&&0{throw e})}function forgotPassword(e){return o=>forgotPasswordDoboard(e).then(e=>{if(console.log("response ",e),"SUCCESS"!==e?.operation_status)throw new Error("Response error");o("New password sent to email","notice");var e=document.getElementById("doboard_task_widget-container-login-forgot-password-form"),t=document.getElementById("doboard_task_widget-input-container-login"),a=document.getElementById("doboard_task_widget-submit_button");e&&e.classList.add("doboard_task_widget-hidden"),t&&(t.classList.remove("doboard_task_widget-hidden"),a)&&a.closest(".doboard_task_widget-field").classList.add("doboard_task_widget-hidden")}).catch(e=>{throw e})}function userUpdate(e,t){var a=localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_user_id"),i=Intl.DateTimeFormat().resolvedOptions().timeZone;return userUpdateDoboard(e,t,a,o,i)}function spotFixSplitUrl(e){try{var t,a,o,i;return e&&""!==e.trim()?(a=(t=new URL(e)).host,0===(o=t.pathname.split("/").filter(Boolean)).length?a:((i=o.reverse()).push(a),i.join(" / "))):""}catch(e){return""}}function setToggleStatus(t){var e=document.getElementById("widget_visibility");e&&(e.checked=!0,e.addEventListener("click",()=>{let e=setTimeout(()=>{localStorage.setItem("spotfix_widget_is_closed","1"),t.hide(),clearTimeout(e)},300)}))}function checkLogInOutButtonsVisible(){var e;localStorage.getItem("spotfix_session_id")?((e=document.getElementById("doboard_task_widget-user_menu-logout_button")?.closest(".doboard_task_widget-user_menu-item"))&&(e.style.display="block"),(e=document.getElementById("doboard_task_widget-input-container-login"))&&e.classList.add("doboard_task_widget-hidden")):((e=document.getElementById("doboard_task_widget-user_menu-logout_button")?.closest(".doboard_task_widget-user_menu-item"))&&(e.style.display="none"),(e=document.getElementById("doboard_task_widget-input-container-login"))&&e.classList.remove("doboard_task_widget-hidden"),clearUserMenuData())}async function clearUserMenuData(){var e=document.querySelector(".doboard_task_widget-user_menu-header-user-name"),t=document.querySelector(".doboard_task_widget-user_menu-header-email"),a=document.querySelector(".doboard_task_widget-user_menu-header-avatar");e&&(e.innerText="Guest"),t&&(t.innerText=""),a&&(a.src=SpotFixSVGLoader.getAsDataURI("iconAvatar"))}function changeSize(e){e&&+localStorage.getItem("maximize")?e.classList.add("doboard_task_widget-container-maximize"):e&&e.classList.remove("doboard_task_widget-container-maximize")}class CleanTalkWidgetDoboard{selectedText="";selectedData={};widgetElement=null;params={};currentActiveTaskId=0;savedIssuesQuantityOnPage=0;savedIssuesQuantityAll=0;allTasksData={};srcVariables={};constructor(e,t){this.selectedData=e||"",this.selectedText=e?.selectedText||"",this.srcVariables={buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),iconEllipsesMore:SpotFixSVGLoader.getAsDataURI("iconEllipsesMore"),iconPlus:SpotFixSVGLoader.getAsDataURI("iconPlus"),iconMaximize:SpotFixSVGLoader.getAsDataURI("iconMaximize"),chevronBack:SpotFixSVGLoader.getAsDataURI("chevronBack"),buttonPaperClip:SpotFixSVGLoader.getAsDataURI("buttonPaperClip"),buttonSendMessage:SpotFixSVGLoader.getAsDataURI("buttonSendMessage"),logoDoBoardGreen:SpotFixSVGLoader.getAsDataURI("logoDoBoardGreen"),logoDoBoardWrap:SpotFixSVGLoader.getAsDataURI("logoDoBoardWrap"),iconSpotWidgetWrapPencil:SpotFixSVGLoader.getAsDataURI("iconSpotWidgetWrapPencil"),iconMarker:SpotFixSVGLoader.getAsDataURI("iconMarker"),iconSpotPublic:SpotFixSVGLoader.getAsDataURI("iconSpotPublic"),iconSpotPrivate:SpotFixSVGLoader.getAsDataURI("iconSpotPrivate"),iconLinkChain:SpotFixSVGLoader.getAsDataURI("iconLinkChain")},this.fileUploader=new FileUploader(this.escapeHtml),this.init(t)}async init(e){this.params=this.getParams();var t=new URLSearchParams(window.location.search),a=t.get("email_confirmation_token");if(a)try{var o=await confirmUserEmail(a,this.params),i=(this.allTasksData=await getAllTasks(this.params),this.currentActiveTaskId=o.taskId,storageSetWidgetIsClosed(!(e="concrete_issue")),t.delete("email_confirmation_token"),window.location.pathname+(t.toString()?"?"+t.toString():""));window.history.replaceState({},document.title,i)}catch(e){this.registrationShowMessage("Error confirming email: "+e.message,"error")}else{a=localStorage.getItem("spotfix_widget_is_closed");(!a||this.selectedText)&&a||(this.allTasksData=await getAllTasks(this.params))}let s;storageTasksHasUnreadUpdates()?s=!0:"wrap_review"===e&&(s=await checkIfTasksHasSiteOwnerUpdates(this.allTasksData,this.params)),storageSaveTasksUpdateData(this.allTasksData),storageWidgetCloseIsSet()||storageSetWidgetIsClosed(!0),s&&storageSetWidgetIsClosed(!1),this.widgetElement=await this.createWidgetElement(e),this.bindWidgetInputsInteractive()}getParams(){var e=document.querySelector('script[src*="doboard-widget-bundle."]');if(!e||!e.src)throw new Error("Script not provided");e=new URL(e.src),e=Object.fromEntries(e.searchParams.entries());if(!e)throw new Error("Script params not provided");if(e.projectToken&&e.accountId&&e.projectId)return e.accountId&&localStorage.setItem("spotfix_company_id",e.accountId),e.projectToken&&localStorage.setItem("spotfix_project_token",e.projectToken),e;throw new Error("Necessary script params not provided")}bindCreateTaskEvents(){var e=document.getElementById("doboard_task_widget-submit_button");e&&e.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-title"),s=e.value;if(s){var t=document.getElementById("doboard_task_widget-description"),r=t.value;if(r){let t="",a="",o="";var d=document.querySelector(".doboard_task_widget-login");if(!!!localStorage.getItem("spotfix_session_id")&&d&&d.classList.contains("active")){let e=document.getElementById("doboard_task_widget-user_email");var d=document.getElementById("doboard_task_widget-user_name"),n=document.getElementById("doboard_task_widget-user_password");if(!(a=e.value))return e.style.borderColor="red",e.focus(),void e.addEventListener("input",function(){this.style.borderColor=""});if(e&&d&&!(t=d.value))return d.style.borderColor="red",d.focus(),void d.addEventListener("input",function(){this.style.borderColor=""});if(e&&n&&!d&&!(o=n.value))return n.style.borderColor="red",n.focus(),void n.addEventListener("input",function(){this.style.borderColor=""})}let e=document.getElementById("doboard_task_widget-user_email");a=e.value;d=document.getElementById("doboard_task_widget-submit_button"),n=(d.disabled=!0,d.innerText=ksesFilter("Creating spot..."),{taskTitle:s,taskDescription:r,selectedData:this.selectedData,projectToken:this.params.projectToken,projectId:this.params.projectId,accountId:this.params.accountId,taskMeta:JSON.stringify(this.selectedData||{pageURL:window.location.href})});a&&(n.userEmail=a),t&&(n.userName=t),o&&(n.userPassword=o),localStorage.setItem("spotfix_pending_task",JSON.stringify({...this.selectedData,description:r}));let i;try{i=await this.submitTask(n)}catch(e){return void this.registrationShowMessage(e.message)}d.disabled=!1,d.style.cursor="pointer",i.needToLogin||(void 0!==i.isPublic&&(this.selectedData.isPublic=i.isPublic),this.allTasksData=await getAllTasks(this.params),storageSaveTasksUpdateData(this.allTasksData),this.selectedData={},await this.createWidgetElement("all_issues"),storageSetWidgetIsClosed(!1),hideContainersSpinner(!1))}else t.style.borderColor="red",t.focus(),t.addEventListener("input",function(){this.style.borderColor=""})}else e.style.borderColor="red",e.focus(),e.addEventListener("input",function(){this.style.borderColor=""})})}resetLoginForm(){var e=document.querySelector(".doboard_task_widget-input-container-login"),t=document.querySelector(".doboard_task_widget-input-container-phantom"),a=document.getElementById("doboard_task_widget-submit_button");e&&e.classList.add("doboard_task_widget-hidden"),t&&t.classList.remove("doboard_task_widget-hidden"),a&&a.closest(".doboard_task_widget-field").classList.remove("doboard_task_widget-hidden")}bindShowLoginFormEvents(){var e=document.getElementById("doboard_task_widget-show_login_form"),t=document.getElementById("doboard_task_widget-on_phantom_login_page"),a=document.getElementById("doboard_task_widget-forgot_password"),o=document.getElementById("doboard_task_widget-forgot_password-black"),i=document.getElementById("doboard_task_widget-login_button"),s=document.getElementById("doboard_task_widget-restore_password_button"),e=(e&&e.addEventListener("click",async()=>{var e=document.querySelector(".doboard_task_widget-input-container-login"),t=document.querySelector(".doboard_task_widget-input-container-phantom"),a=document.getElementById("doboard_task_widget-submit_button");e&&(e.classList.toggle("doboard_task_widget-hidden"),a)&&(e.classList.contains("doboard_task_widget-hidden")?a.closest(".doboard_task_widget-field").classList.remove("doboard_task_widget-hidden"):a.closest(".doboard_task_widget-field").classList.add("doboard_task_widget-hidden")),t&&t.classList.toggle("doboard_task_widget-hidden")}),t&&t.addEventListener("click",async()=>{var e=document.querySelector(".doboard_task_widget-input-container-login"),t=document.querySelector(".doboard_task_widget-input-container-phantom"),a=document.getElementById("doboard_task_widget-submit_button");e&&(e.classList.toggle("doboard_task_widget-hidden"),a)&&(e.classList.contains("doboard_task_widget-hidden")?a.closest(".doboard_task_widget-field").classList.remove("doboard_task_widget-hidden"):a.closest(".doboard_task_widget-field").classList.add("doboard_task_widget-hidden")),t&&t.classList.toggle("doboard_task_widget-hidden")}),a&&(a.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-container-login-forgot-password-form"),t=document.getElementById("doboard_task_widget-input-container-login");e&&e.classList.remove("doboard_task_widget-hidden"),t&&t.classList.add("doboard_task_widget-hidden")}),o.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-container-login-forgot-password-form"),t=document.getElementById("doboard_task_widget-input-container-login"),a=document.getElementById("doboard_task_widget-submit_button");e&&e.classList.add("doboard_task_widget-hidden"),t&&(t.classList.remove("doboard_task_widget-hidden"),a)&&a.closest(".doboard_task_widget-field").classList.add("doboard_task_widget-hidden")})),document.querySelector(".doboard_task_widget-input-container-login-menu #doboard_task_widget-forgot_password")),t=(e&&e.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-container-login-forgot-password-form"),t=document.querySelector(".doboard_task_widget-input-container-login-menu");e&&e.classList.remove("doboard_task_widget-hidden"),t&&t.classList.add("doboard_task_widget-hidden")}),document.querySelector(".doboard_task_widget-input-container-login-menu ~ #doboard_task_widget-container-login-forgot-password-form #doboard_task_widget-forgot_password-black")),a=(t&&t.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-container-login-forgot-password-form"),t=document.querySelector(".doboard_task_widget-input-container-login-menu");e&&e.classList.add("doboard_task_widget-hidden"),t&&t.classList.remove("doboard_task_widget-hidden")}),i&&i.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-login_email"),t=document.getElementById("doboard_task_widget-login_password"),a=(document.querySelector(".doboard_task_widget-login-is-invalid").classList.add("doboard_task_widget-hidden"),e.value.trim());if(a)if(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a)){var o=t.value;if(o)if(o.length<6)t.style.borderColor="red",t.focus(),t.addEventListener("input",function(){this.style.borderColor=""});else{try{await loginUser({userEmail:a,userPassword:o})(this.registrationShowMessage),this.setUserMenuData();var i=document.getElementById("doboard_task_widget-submit_button");i&&i.closest(".doboard_task_widget-field").classList.remove("doboard_task_widget-hidden")}catch(e){document.querySelector(".doboard_task_widget-login-is-invalid").classList.remove("doboard_task_widget-hidden")}a=!!localStorage.getItem("spotfix_session_id"),o=localStorage.getItem("spotfix_email");a&&o&&!o.includes("spotfix_")?document.querySelector(".doboard_task_widget-login")?.classList?.add("doboard_task_widget-hidden"):document.querySelector(".doboard_task_widget-login-is-invalid").classList.remove("doboard_task_widget-hidden")}else t.style.borderColor="red",t.focus(),t.addEventListener("input",function(){this.style.borderColor=""})}else e.style.borderColor="red",e.focus(),e.addEventListener("input",function(){this.style.borderColor=""});else e.style.borderColor="red",e.focus(),e.addEventListener("input",function(){this.style.borderColor=""})}),document.getElementById("doboard_task_widget-password-toggle"));let r=document.getElementById("doboard_task_widget-login_password");a&&r&&a.addEventListener("click",function(){var e="password"===r.type;r.type=e?"text":"password",this.classList.toggle("doboard_task_widget-bottom-eye-off-icon"),this.classList.toggle("doboard_task_widget-bottom-eye-icon")}),s&&s.addEventListener("click",async()=>{var e=document.getElementById("doboard_task_widget-forgot_password_email"),t=e.value.trim();if(t)if(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t))try{await forgotPassword(t)(this.registrationShowMessage)}catch(e){this.registrationShowMessage(e.message,"error")}else e.style.borderColor="red",e.focus();else e.style.borderColor="red",e.focus(),e.addEventListener("input",function(){this.style.borderColor=""})})}async createWidgetElement(e,r=!1){var d=document.querySelector(".doboard_task_widget")?document.querySelector(".doboard_task_widget"):document.createElement("div");d.className="doboard_task_widget",d.innerHTML=ksesFilter(""),d.removeAttribute("style");let t="",n,l={};var a=window.SpotfixWidgetConfig;switch(e){case"create_issue":t="create_issue",this.type_name=t,l={selectedText:this.selectedText,currentDomain:document.location.hostname||"",buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),iconMaximize:SpotFixSVGLoader.getAsDataURI("iconMaximize"),iconEllipsesMore:SpotFixSVGLoader.getAsDataURI("iconEllipsesMore"),...this.srcVariables},storageGetUserIsDefined()&&storageSetWidgetIsClosed(!1);break;case"wrap":if(storageGetWidgetIsClosed())return;t="wrap",l={position:Number.isNaN(Number(a?.verticalPosition))?"0vh":Number(a?.verticalPosition)+"vh",...this.srcVariables};break;case"wrap_review":t="wrap_review",l={position:Number.isNaN(Number(a?.verticalPosition))?"0vh":Number(a?.verticalPosition)+"vh",...this.srcVariables};break;case"all_issues":t="all_issues",this.type_name=t,l={...this.srcVariables};break;case"user_menu":t="user_menu";var o=localStorage.getItem("spotfix_app_version")||SPOTFIX_VERSION;l={spotfixVersion:o?"Spotfix version "+o+".":"",avatar:SpotFixSVGLoader.getAsDataURI("iconAvatar"),iconEye:SpotFixSVGLoader.getAsDataURI("iconEye"),iconDoor:SpotFixSVGLoader.getAsDataURI("iconDoor"),chevronBackDark:SpotFixSVGLoader.getAsDataURI("chevronBackDark"),buttonCloseScreen:SpotFixSVGLoader.getAsDataURI("buttonCloseScreen"),userName:"Guest",email:localStorage.getItem("spotfix_email")||"",...this.srcVariables};break;case"concrete_issue":t="concrete_issue",this.type_name=t,this.savedIssuesQuantityAll=Array.isArray(this.allTasksData)?this.allTasksData.length:0,this.savedIssuesQuantityOnPage=Array.isArray(this.allTasksData)?this.allTasksData.filter(e=>{try{return(e.taskMeta?JSON.parse(e.taskMeta):{}).pageURL===window.location.href}catch(e){return!1}}).length:0,l={issueTitle:"...",issueComments:[],issuesCounter:getIssuesCounterString(this.savedIssuesQuantityOnPage,this.savedIssuesQuantityAll),...this.srcVariables}}d.innerHTML=this.loadTemplate(t,l),document.body.appendChild(d),spotFixRemoveHighlights();var c=document.querySelector(".doboard_task_widget-container");switch(e){case"create_issue":c&&+localStorage.getItem("maximize")?c.classList.add("doboard_task_widget-container-maximize"):c&&c.classList.remove("doboard_task_widget-container-maximize");var g=window.getSelection(),_=!!localStorage.getItem("spotfix_session_id"),p=localStorage.getItem("spotfix_email");_&&p&&!p.includes("spotfix_")&&document.querySelector(".doboard_task_widget-login").classList.add("hidden"),"Range"===g.type&&(spotFixScrollToNodePath(spotFixGetSelectedData(g).nodePath),this.positionWidgetContainer()),this.bindCreateTaskEvents(),this.bindShowLoginFormEvents();break;case"wrap":await this.getTaskCount(),document.querySelector(".doboard_task_widget-wrap").addEventListener("click",e=>{e=e.currentTarget.classList;e&&!e.contains("hidden")&&this.createWidgetElement("all_issues")}),hideContainersSpinner(!1);break;case"wrap_review":document.querySelector("#doboard_task_widget_button").addEventListener("click",e=>{spotFixOpenWidget(this.selectedData,"create_issue")});break;case"all_issues":changeSize(c),spotFixRemoveHighlights();let i=0;this.allTasksData?.length||(this.allTasksData=await getAllTasks(this.params));var _=this.allTasksData,u=(n=await getTasksFullDetails(this.params,_,this.currentActiveTaskId),[]);if(0<_.length){let a=window.location.href;var m=_.sort((e,t)=>{e=JSON.parse(e.taskMeta).pageURL===a?1:0;return(JSON.parse(t.taskMeta).pageURL===a?1:0)-e});document.querySelector(".doboard_task_widget-all_issues-container").innerHTML="";for(let o=0;oThe issues list is empty ')),this.bindIssuesClick(),hideContainersSpinner(!1);break;case"user_menu":setToggleStatus(this),checkLogInOutButtonsVisible();p=await getUserDetails(this.params),g=await getReleaseVersion(),_=localStorage.getItem("spotfix_app_version")||g||SPOTFIX_VERSION;l.spotfixVersion=(_?`Spotfix version ${_}.`:"")||"",p&&(l.userName=p.name||"Guest",l.email=p.email||localStorage.getItem("spotfix_email")||"",p?.avatar?.s)&&(l.avatar=p?.avatar?.s),d.innerHTML=this.loadTemplate("user_menu",l),document.body.appendChild(d),setToggleStatus(this),checkLogInOutButtonsVisible(),this.bindShowLoginFormEvents(),this.bindWidgetInputsInteractive();break;case"concrete_issue":changeSize(c);let a=await getTaskFullDetails(n=await getTasksFullDetails(this.params,this.allTasksData,this.currentActiveTaskId),this.currentActiveTaskId);g=document.querySelector(".doboard_task_widget-issue-title");g&&(g.innerText=ksesFilter(a.issueTitle)),l.issueTitle=a?.issueTitle,l.issueComments=a?.issueComments;let t=null;_=this.allTasksData.find(e=>String(e.taskId)===String(a.taskId));let o=null;if(_&&_.taskMeta)try{o=JSON.parse(_.taskMeta),t=o.nodePath||null}catch(e){t=null,o=null}l.taskPageUrl=o.pageURL;var p=o.pageURL.replace(window.location.origin,""),g=(l.taskFormattedPageUrl=p.length<2?o.pageURL.replace(window.location.protocol+"/",""):p,l.contenerClasess=+localStorage.getItem("maximize")?"doboard_task_widget-container-maximize doboard_task_widget-container":"doboard_task_widget-container",d.innerHTML=this.loadTemplate("concrete_issue",l),document.body.appendChild(d),spotFixRemoveHighlights(),o&&t&&(spotFixHighlightElements([o],this),"function"==typeof spotFixScrollToNodePath)&&spotFixScrollToNodePath(t),document.querySelector(".doboard_task_widget-concrete_issues-container")),v=[],I=localStorage.getItem("spotfix_user_id");if(0e.commentTime.localeCompare(t.commentTime)),T){var E=T[L];e+=this.loadTemplate("concrete_issue_messages",E)}t+=this.loadTemplate("concrete_issue_day_content",{dayContentMonthDay:C,dayContentMessages:e,statusFixedHtml:"DONE"!==n?.taskStatus?"":this.loadTemplate("fixedTaskHtml")})}g.innerHTML=t}else g.innerHTML=ksesFilter("No comments");_=document.querySelector(".doboard_task_widget-send_message_input");function D(){40{var e=document.querySelector(".doboard_task_widget-content");e.scrollTo({top:e.scrollHeight,behavior:"smooth"})},0);let s=document.querySelector(".doboard_task_widget-send_message_button");if(s){this.fileUploader.init();let o=this;s.addEventListener("click",async t=>{t.preventDefault();var t=s.closest(".doboard_task_widget-send_message").querySelector(".doboard_task_widget-send_message_input"),a=t.value.trim();if(a){t.disabled=!0,s.disabled=!0;let e=null;try{e=await addTaskComment(this.params,this.currentActiveTaskId,a),t.value="",await this.createWidgetElement("concrete_issue"),hideContainersSpinner(!1)}catch(e){alert("Error when adding a comment: "+e.message)}o.fileUploader.hasFiles()&&null!==e&&e.hasOwnProperty("commentId")&&(a=localStorage.getItem("spotfix_session_id"),(a=await o.fileUploader.sendAttachmentsForComment(o.params,a,e.commentId)).success||(o.fileUploader.showError("Some files where no sent, see details in the console."),a=JSON.stringify(a),console.log(a))),t.disabled=!1,s.disabled=!1}})}}e=document.querySelector(".doboard_task_widget_return_to_all");let i=this;e&&e.addEventListener("click",function(e,t=i){t.createWidgetElement("all_issues")});e=document.querySelector(".doboard_task_widget-send_message_paperclip");return e&&this.fileUploader.bindPaperClipAction(e),document.querySelector(".doboard_task_widget-close_btn")?.addEventListener("click",e=>{this.hide()}),document.querySelector("#openUserMenuButton")?.addEventListener("click",()=>{this.createWidgetElement("user_menu")}),document.querySelector("#doboard_task_widget-user_menu-logout_button")?.addEventListener("click",()=>{logoutUserDoboard(this.params.projectToken)}),document.getElementById("addNewTaskButton")?.addEventListener("click",()=>{spotFixShowWidget()}),document.getElementById("maximizeWidgetContainer")?.addEventListener("click",()=>{var e=document.querySelector(".doboard_task_widget-container");+localStorage.getItem("maximize")&&e.classList.contains("doboard_task_widget-container-maximize")?(localStorage.setItem("maximize","0"),e.classList.remove("doboard_task_widget-container-maximize")):(localStorage.setItem("maximize","1"),e.classList.add("doboard_task_widget-container-maximize"))}),document.querySelector("#doboard_task_widget-user_menu-signlog_button")?.addEventListener("click",()=>{spotFixShowWidget()}),document.querySelector("#spotfix_back_button")?.addEventListener("click",()=>{this.createWidgetElement(this.type_name),this.bindWidgetInputsInteractive()}),d}bindIssuesClick(){document.querySelectorAll(".issue-item").forEach(e=>{e.addEventListener("click",async()=>{let t=null;try{t=JSON.parse(e.getAttribute("data-node-path"))}catch(e){t=null}t&&spotFixScrollToNodePath(t),this.currentActiveTaskId=e.getAttribute("data-task-id"),await this.showOneTask()})})}async showOneTask(){await this.createWidgetElement("concrete_issue");var e=this.getTaskHighlightData(this.currentActiveTaskId);e&&(spotFixRemoveHighlights(),spotFixHighlightElements([e],this),this.positionWidgetContainer()),hideContainersSpinner(!1)}loadTemplate(t,e={}){let a=SpotFixTemplatesLoader.getTemplateCode(t);for(var[o,i]of Object.entries(e)){o=`{{${o}}}`;let e;e=this.isPlaceholderInAttribute(a,o)?this.escapeHtml(String(i)):ksesFilter(String(i),{template:t,imgFilter:!0}),a=a.replaceAll(o,e)}return ksesFilter(a,{template:t})}isPlaceholderInAttribute(e,t){t=t.replace(/[{}]/g,"\\$&");return new RegExp(`[\\w-]+\\s*=\\s*["'][^"']*${t}[^"']*["']`,"g").test(e)}escapeHtml=e=>e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'");async getTaskCount(){if(!localStorage.getItem("spotfix_session_id"))return{};var e=this.params.projectToken,t=localStorage.getItem("spotfix_session_id"),a=localStorage.getItem("spotfix_tasks_count");let o;o=0===a||a?a:(await getTasksDoboard(e,t,this.params.accountId,this.params.projectId),(await spotfixIndexedDB.getAll(TABLE_TASKS)).filter(e=>e.taskMeta).length);a=document.getElementById("doboard_task_widget-task_count");a&&(a.innerText=ksesFilter(o),a.classList.remove("hidden"))}async submitTask(e){localStorage.getItem("spotfix_session_id")||(await registerUser(e)(this.registrationShowMessage),e.userPassword&&(await loginUser(e)(this.registrationShowMessage),checkLogInOutButtonsVisible()));var t=localStorage.getItem("spotfix_session_id");return t?handleCreateTask(t,e):{needToLogin:!0}}hide(){spotFixRemoveHighlights(),this.createWidgetElement("wrap")}wrapElementWithSpotfixHighlight(e){var t=e.cloneNode(),a=document.createElement("span");return a.className="doboard_task_widget-text_selection image-highlight",e.insertAdjacentElement("beforebegin",a),a.appendChild(t),a}getTaskHighlightData(t){var e=this.allTasksData.find(e=>e.taskId.toString()===t.toString());if(e&&void 0!==e.taskMeta){let t=null;try{t=JSON.parse(e.taskMeta)}catch(e){t=null}if(null!==t&&"object"==typeof t)return t}return null}bindWidgetInputsInteractive(){document.querySelectorAll(".doboard_task_widget-field").forEach(e=>{e.value&&e.classList.add("has-value"),e.addEventListener("input",()=>{e.value?e.classList.add("has-value"):e.classList.remove("has-value")}),e.addEventListener("blur",()=>{e.value||e.classList.remove("has-value")})});var t=document.querySelector(".doboard_task_widget-login span");if(t){let e=this;t.addEventListener("click",function(){this.closest(".doboard_task_widget-login").classList.toggle("active"),e.positionWidgetContainer(),setTimeout(()=>{var e=document.querySelector(".doboard_task_widget-content");e.scrollTo({top:e.scrollHeight,behavior:"smooth"})},0)})}window.addEventListener("scroll",this.handleScroll.bind(this)),window.addEventListener("resize",this.handleResize.bind(this))}registrationShowMessage(e,t="error"){var a=document.getElementById("doboard_task_widget-error_message-header"),o=document.getElementById("doboard_task_widget-error_message"),i=document.querySelector(".doboard_task_widget-message-wrapper");"string"==typeof e&&null!==o&&null!==i&&(o.innerText=ksesFilter(e),i.classList.remove("hidden"),o.classList.remove("doboard_task_widget-notice_message","doboard_task_widget-error_message"),"notice"===t?(a.innerText=ksesFilter(""),i.classList.add("doboard_task_widget-notice_message"),o.style.color="#2a5db0"):(a.innerText=ksesFilter("Registration error"),i.classList.add("doboard_task_widget-error_message"),o.style.color="red"))}positionWidgetContainer(){var t=document.querySelector(".doboard_task_widget-text_selection"),a=document.querySelector(".doboard_task_widget"),o=document.querySelector(".doboard_task_widget-content.doboard_task_widget-create_issue"),i=document.querySelector(".doboard_task_widget-concrete_issues-container");if((o||i)&&t){var o=window.scrollY,i=window.innerHeight,t=t.getBoundingClientRect().top+o,s=a.offsetHeight;let e;t-o<0?e=10:(i{this.positionWidgetContainer()},10)}handleResize(){clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(()=>{this.positionWidgetContainer()},100)}isSpotHaveToBeHighlighted(e){return!0}sanitizeNodePath(e){e=Array.isArray(e)?JSON.stringify(e):String(e);return/^[\[\]0-9,\s]*$/.test(e)?e:""}async setUserMenuData(){var e=this.params;let t=null;if(localStorage.getItem("spotfix_session_id"))try{t=await getUserDetails(e)}catch(e){console.error("Error fetching user details:",e)}var e=document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 16px"]'),a=document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 12px"]'),o=document.querySelector(".doboard_task_widget-user_menu-header-avatar");e&&(t&&t.name?e.innerText=t.name:e.innerText="Guest"),a&&(t&&t.email?a.innerText=t.email:(e=localStorage.getItem("spotfix_email")||"",a.innerText=e.includes("spotfix_")?"":e)),o&&(t&&t.avatar&&t.avatar.s?o.src=t.avatar.s:o.src="")}}var spotFixShowDelayTimeout=null;let SPOTFIX_DEBUG=!1,SPOTFIX_SHOW_DELAY=1e3;function spotFixInit(){spotfixIndexedDB.init(),wsSpotfix.connect(),wsSpotfix.subscribe(),new SpotFixSourcesLoader,new CleanTalkWidgetDoboard({},"wrap"),loadBotDetector()}function loadBotDetector(){var e;document.querySelector('script[src="https://moderate.cleantalk.org/ct-bot-detector-wrapper.js"]')||document.getElementById("ct-bot-detector-script")||((e=document.createElement("script")).src="https://moderate.cleantalk.org/ct-bot-detector-wrapper.js",e.async=!0,e.id="ct-bot-detector-script",document.head.appendChild(e))}function spotFixShowWidget(){new CleanTalkWidgetDoboard(null,"create_issue")}function spotFixIsInsideWidget(t){if(t){let e=t.nodeType===Node.ELEMENT_NODE?t:t.parentElement;for(;e;){if(e.classList&&e.classList.contains("doboard_task_widget"))return!0;e=e.parentElement}}return!1}function spotFixOpenWidget(e,t){e&&new CleanTalkWidgetDoboard(e,t)}function spotFixDebugLog(e){SPOTFIX_DEBUG&&console.log(e)}function hideContainersSpinner(){var t=document.getElementsByClassName("doboard_task_widget-spinner_wrapper_for_containers");if(0e?.taskId?.toString()===t?.toString());let i=e.users,o=0String(e.user_id)===String(o.userId))),"");o&&((e=formatDate(o.commentDate)).date,r=e.time);var e=getAvatarSrc(s),d=getAuthorName(s);return{taskId:t,taskAuthorAvatarImgSrc:e,taskAuthorName:d,lastMessageText:o?o.commentBody:"No messages yet",lastMessageTime:r,issueTitle:0new Date(e.commentDate)-new Date(t.commentDate)).map(t=>{var{date:e,time:a}=formatDate(t.commentDate);let o=null;return{commentAuthorAvatarSrc:getAvatarSrc(o=i&&0String(e.user_id)===String(t.userId)):o),commentAuthorName:getAuthorName(o),commentBody:t.commentBody,commentDate:e,commentTime:a,commentUserId:t.userId||"Unknown User"}})}}function getAvatarData(e){let t,a;var o=e.taskAuthorName&&"Anonymous"!=e.taskAuthorName?e.taskAuthorName.trim().charAt(0).toUpperCase():null;let i="doboard_task_widget-avatar-initials";return null===e.taskAuthorAvatarImgSrc&&null!==o&&(t="display: flex;background-color: #f8de7e;justify-content: center;align-items: center;",a="doboard_task_widget-avatar_container"),null===e.taskAuthorAvatarImgSrc&&null===o&&(t="background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAE9GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4wLWMwMDAgNzkuMTcxYzI3ZmFiLCAyMDIyLzA4LzE2LTIyOjM1OjQxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjQuMCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjQtMDQtMTBUMTk6MDg6MDkrMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxNWRjOWI0Yy04ZWVmLTRkNTEtYmE0MS1kOTkzZTZmNjNmMTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTVkYzliNGMt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');",a="doboard_task_widget-avatar_container",i+=" doboard_task_widget-hidden_element"),null!==e.taskAuthorAvatarImgSrc&&(t=`background-image:url('${e.taskAuthorAvatarImgSrc}');`,a="doboard_task_widget-avatar_container",i="doboard_task_widget-hidden_element"),{avatarStyle:t,avatarCSSClass:a,taskAuthorInitials:o,initialsClass:i}}function isAnyTaskUpdated(t){var a=[];for(let e=0;e{var t=e.name.toLowerCase();l[a]?.includes(t)&&!t.startsWith("on")&&!e.value.toLowerCase().includes("javascript:")||o.removeAttribute(e.name)})}[...o.childNodes].forEach(e)}),c.body.innerHTML}"loading"!==document.readyState?document.addEventListener("spotFixLoaded",spotFixInit):document.addEventListener("DOMContentLoaded",spotFixInit),document.addEventListener("selectionchange",function(e){var t;e.target===document&&(e=!!document.getElementsByClassName("wrap_review")[0],(t=document.getSelection())&&""!==t.toString()||!e?(spotFixShowDelayTimeout&&clearTimeout(spotFixShowDelayTimeout),spotFixShowDelayTimeout=setTimeout(()=>{var e,t,a=window.getSelection();"Range"===a.type&&(t=a.anchorNode,e=a.focusNode,spotFixIsInsideWidget(t)||spotFixIsInsideWidget(e)||(t=spotFixGetSelectedData(a))&&spotFixOpenWidget(t,"wrap_review"))},SPOTFIX_SHOW_DELAY)):new CleanTalkWidgetDoboard({},"wrap"))});let SPOTFIX_SELECTION_TYPE_TEXT="text",SPOTFIX_SELECTION_TYPE_IMG="image",SPOTFIX_SELECTION_TYPE_ELEMENT="element";function spotFixGetSelectionType(e){var t=e.getRangeAt(0),a=t.commonAncestorContainer;return spotFixGetSelectedImage(e)?SPOTFIX_SELECTION_TYPE_IMG:a.nodeType===Node.ELEMENT_NODE&&1s&&(s=o.length),r=spotFixCalculateNodePath(n);break;case SPOTFIX_SELECTION_TYPE_IMG:var n=t.startContainer,l=spotFixGetSelectedImage(e);o=`Image (${l.alt||"no description"})`,r=spotFixCalculateNodePath(l),i=Array.from(n.parentNode.children).indexOf(n),s=i+1;break;case SPOTFIX_SELECTION_TYPE_ELEMENT:l=d.nodeType===Node.ELEMENT_NODE?d:d.parentElement;if(l.childNodes.length<=1)return spotFixDebugLog("`spotFixGetSelectedData` skip by `Selection have not inner data`"),null;o=l.textContent||"",r=spotFixCalculateNodePath(l),i=Array.from(l.parentNode.children).indexOf(l),s=i+1}var c=window.location.href;return{startSelectPosition:i,endSelectPosition:s,selectedText:o.trim(),pageURL:c,nodePath:r,selectionType:a,imageUrl:(SPOTFIX_SELECTION_TYPE_IMG,"")}}function spotFixHighlightElements(e,o){if(0!==e.length){let a=new Map;e.forEach(e=>{var t;e?.nodePath&&Array.isArray(e?.nodePath)?this.spotFixIsValidNodePath(e.nodePath)?(t=spotFixRetrieveNodeFromPath(e.nodePath))?e.selectionType?e.selectionType&&![SPOTFIX_SELECTION_TYPE_TEXT,SPOTFIX_SELECTION_TYPE_IMG,SPOTFIX_SELECTION_TYPE_ELEMENT].includes(e.selectionType)?spotFixDebugLog("Invalid selection type: "+e.selectionType):(a.has(t)||a.set(t,[]),a.get(t).push(e)):spotFixDebugLog("Selection type is not provided."):spotFixDebugLog("Element not found for path: "+e.nodePath):spotFixDebugLog("Invalid nodePath format: "+e.nodePath):spotFixDebugLog("Invalid spot: missing or invalid nodePath: "+e)}),a.forEach((e,t)=>{var a=e[0].selectionType;switch(a){case"image":this.spotFixHighlightImageElement(t);break;case"element":this.spotFixHighlightNestedElement(t);break;case"text":this.spotFixHighlightTextInElement(t,e,o);break;default:spotFixDebugLog("Unknown selection type: "+a)}})}}function spotFixHighlightImageElement(e){"IMG"!==e.tagName?spotFixDebugLog("Expected IMG element for image highlight, got: "+e.tagName):e.classList.add("doboard_task_widget-image_selection")}function spotFixHighlightNestedElement(e){e.classList.add("doboard_task_widget-element_selection")}function spotFixHighlightTextInElement(e,t,i){let a="";let s=`${`
${a=t[0].isFixed?"This issue already fixed.":"We are already working on this issue."}
You can see history Here
-
`} `,r=e.textContent;var d=t[0].selectedText;if(d){let o=[];if(t.forEach(e=>{var t=parseInt(e.startSelectPosition)||0,a=parseInt(e.endSelectPosition)||0;t<0||a>r.length||at.position-e.position),r.slice(o[1].position,o[0].position)!==d)spotFixDebugLog("It is not allow to highlight element by provided metadata.");else{let a=r;o.forEach(e=>{var t="start"===e.type?s:" ";a=a.slice(0,e.position)+t+a.slice(e.position)});try{e.innerHTML=ksesFilter(a),document.querySelectorAll(".doboard_task_widget-see-task").forEach(a=>{a.addEventListener("click",e=>{e.preventDefault();e=a.className.split(" ").find(e=>e.includes("__task-id-"));let t=null;(t=e?e.split("__task-id-")[1]:t)&&(i.currentActiveTaskId=t,i.showOneTask())})})}catch(e){spotFixDebugLog("Error updating element content: "+e)}}}else spotFixDebugLog("Provided metadata is invalid.")}function spotFixScrollToNodePath(e){e=spotFixRetrieveNodeFromPath(e);return!(!e||!e.scrollIntoView||(e.scrollIntoView({behavior:"smooth",block:"center"}),0))}function spotFixRemoveHighlights(){var e=document.querySelectorAll(".doboard_task_widget-text_selection");let o=new Set,t=(e.forEach(e=>{var t=e.parentNode,a=(o.add(t),e.querySelector(".doboard_task_widget-text_selection_tooltip"));for(a&&a.remove();e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}),o.forEach(e=>e.normalize()),"doboard_task_widget-element_selection"),a=(document.querySelectorAll("."+t).forEach(e=>{e.classList.remove(t)}),"doboard_task_widget-image_selection");document.querySelectorAll("."+a).forEach(e=>{e.classList.remove(a)})}function spotFixIsValidNodePath(e){return!!Array.isArray(e)&&0!==e.length&&e.every(e=>Number.isInteger(e)&&0<=e&&e<1e3)}function spotFixGetSelectedImage(e){if(e&&0!==e.rangeCount&&!e.isCollapsed){let t=e.getRangeAt(0);if(t.startContainer===t.endContainer&&t.startContainer.nodeType===Node.ELEMENT_NODE&&"IMG"===t.startContainer.tagName)return t.startContainer;e=document.createTreeWalker(t.commonAncestorContainer,NodeFilter.SHOW_ELEMENT,{acceptNode:function(e){return"IMG"===e.tagName&&spotFixIsElementInRange(e,t)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}}).nextNode();if(e)return e;var a,e=spotFixGetElementFromNode(t.startContainer),o=spotFixGetElementFromNode(t.endContainer);if(e&&"IMG"===e.tagName&&spotFixIsElementPartiallySelected(e,t))return e;if(o&&"IMG"===o.tagName&&spotFixIsElementPartiallySelected(o,t))return o;for(a of spotFixFindNearbyElements(t))if("IMG"===a.tagName)return a}return null}function spotFixIsElementInRange(e,t){var a=document.createRange();return a.selectNode(e),t.compareBoundaryPoints(Range.START_TO_START,a)<=0&&0<=t.compareBoundaryPoints(Range.END_TO_END,a)}function spotFixIsElementPartiallySelected(e,t){e=e.getBoundingClientRect(),t=t.getBoundingClientRect();return!(e.rightt.right||e.bottomt.bottom)}function spotFixGetElementFromNode(e){return e.nodeType===Node.ELEMENT_NODE?e:e.parentElement}function spotFixFindNearbyElements(t){var a=[],e=t.commonAncestorContainer,o=e.previousElementSibling,i=e.nextElementSibling;if(o&&a.push(o),i&&a.push(i),e.nodeType===Node.ELEMENT_NODE){var s=e.children;for(let e=0;e{e.taskId&&e.taskLastUpdate&&(t[e.taskId]={taskId:e.taskId,taskLastUpdate:e.taskLastUpdate})}),localStorage.setItem("spotfix_task_updates",JSON.stringify(t))}}function storageSaveTasksCount(e){e&&Array.isArray(e)&&(e=e.filter(e=>e.taskMeta)?.length,localStorage.setItem("spotfix_tasks_count",""+e))}function storageCheckTaskUpdate(e,t){if(!e||!t)return null;let a={};try{a=JSON.parse(localStorage.getItem("spotfix_task_updates")||"{}")}catch(e){a={}}e=a[e];return!!e&&new Date(e.taskLastUpdate)e!==a),localStorage.setItem("spotfix_unread_updates",JSON.stringify(t))}}function storageTasksHasUnreadUpdates(){let t=[];try{t=JSON.parse(localStorage.getItem("spotfix_unread_updates")||"[]")}catch(e){t=[]}return 0this.handleFileInputChange(e))}bindPaperClipAction(e){e.addEventListener("click",e=>{e.preventDefault(),this.fileInput&&this.fileInput.click()})}handleFileInputChange(e){this.clearError();var t=Array.from(e.target.files);this.files.length+t.length>this.maxFiles?this.showError(`Maximum ${this.maxFiles} files can be attached.`):(t.filter(e=>this.validateFile(e)).forEach(e=>this.addFile(e)),e.target.value="",this.uploaderWrapper.style.display="block")}validateFile(e){return e.size>this.maxFileSize?(this.showError(`File "${e.name}" is too large. Maximum size: `+this.formatFileSize(this.maxFileSize)),!1):this.getTotalSize()+e.size>this.maxTotalSize?(this.showError("Total files size exceeded. Maximum: "+this.formatFileSize(this.maxTotalSize)),!1):!(0e+t.file.size,0)}addFile(e){e={id:this.generateFileId(),file:e};this.files.push(e),this.renderFileList()}generateFileId(){return Date.now()+Math.random().toString(36).substr(2,9)}removeFile(t){this.files=this.files.filter(e=>e.id!==t),this.renderFileList(),this.clearError()}renderFileList(){var e;this.fileList&&(0===this.files.length?this.fileList.innerHTML=ksesFilter('No files attached
'):(e=this.files.map(e=>this.createFileItem(e)),this.fileList.innerHTML=ksesFilter(""),e.forEach(e=>this.fileList.appendChild(e))))}createFileItem(e){let{file:t,id:a}=e;e=document.createElement("div");return e.className="doboard_task_widget__file-upload__file-item",e.innerHTML=ksesFilter(`
+ `} `,r=e.textContent;var d=t[0].selectedText;if(d){let o=[];if(t.forEach(e=>{var t=parseInt(e.startSelectPosition)||0,a=parseInt(e.endSelectPosition)||0;t<0||a>r.length||at.position-e.position),r.slice(o[1].position,o[0].position)!==d)spotFixDebugLog("It is not allow to highlight element by provided metadata.");else{let a=r;o.forEach(e=>{var t="start"===e.type?s:" ";a=a.slice(0,e.position)+t+a.slice(e.position)});try{e.innerHTML=ksesFilter(a),document.querySelectorAll(".doboard_task_widget-see-task").forEach(a=>{a.addEventListener("click",e=>{e.preventDefault();e=a.className.split(" ").find(e=>e.includes("__task-id-"));let t=null;(t=e?e.split("__task-id-")[1]:t)&&(i.currentActiveTaskId=t,i.showOneTask())})})}catch(e){spotFixDebugLog("Error updating element content: "+e)}}}else spotFixDebugLog("Provided metadata is invalid.")}function spotFixScrollToNodePath(e){e=spotFixRetrieveNodeFromPath(e);return!(!e||!e.scrollIntoView||(e.scrollIntoView({behavior:"smooth",block:"center"}),0))}function spotFixRemoveHighlights(){var e=document.querySelectorAll(".doboard_task_widget-text_selection");let o=new Set,t=(e.forEach(e=>{var t=e.parentNode,a=(o.add(t),e.querySelector(".doboard_task_widget-text_selection_tooltip"));for(a&&a.remove();e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}),o.forEach(e=>e.normalize()),"doboard_task_widget-element_selection"),a=(document.querySelectorAll("."+t).forEach(e=>{e.classList.remove(t)}),"doboard_task_widget-image_selection");document.querySelectorAll("."+a).forEach(e=>{e.classList.remove(a)})}function spotFixIsValidNodePath(e){return!!Array.isArray(e)&&0!==e.length&&e.every(e=>Number.isInteger(e)&&0<=e&&e<1e3)}function spotFixGetSelectedImage(e){if(e&&0!==e.rangeCount&&!e.isCollapsed){let t=e.getRangeAt(0);if(t.startContainer===t.endContainer&&t.startContainer.nodeType===Node.ELEMENT_NODE&&"IMG"===t.startContainer.tagName)return t.startContainer;e=document.createTreeWalker(t.commonAncestorContainer,NodeFilter.SHOW_ELEMENT,{acceptNode:function(e){return"IMG"===e.tagName&&spotFixIsElementInRange(e,t)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}}).nextNode();if(e)return e;var a,e=spotFixGetElementFromNode(t.startContainer),o=spotFixGetElementFromNode(t.endContainer);if(e&&"IMG"===e.tagName&&spotFixIsElementPartiallySelected(e,t))return e;if(o&&"IMG"===o.tagName&&spotFixIsElementPartiallySelected(o,t))return o;for(a of spotFixFindNearbyElements(t))if("IMG"===a.tagName)return a}return null}function spotFixIsElementInRange(e,t){var a=document.createRange();return a.selectNode(e),t.compareBoundaryPoints(Range.START_TO_START,a)<=0&&0<=t.compareBoundaryPoints(Range.END_TO_END,a)}function spotFixIsElementPartiallySelected(e,t){e=e.getBoundingClientRect(),t=t.getBoundingClientRect();return!(e.rightt.right||e.bottomt.bottom)}function spotFixGetElementFromNode(e){return e.nodeType===Node.ELEMENT_NODE?e:e.parentElement}function spotFixFindNearbyElements(t){var a=[],e=t.commonAncestorContainer,o=e.previousElementSibling,i=e.nextElementSibling;if(o&&a.push(o),i&&a.push(i),e.nodeType===Node.ELEMENT_NODE){var s=e.children;for(let e=0;e{e.taskId&&e.taskLastUpdate&&(t[e.taskId]={taskId:e.taskId,taskLastUpdate:e.taskLastUpdate})}),localStorage.setItem("spotfix_task_updates",JSON.stringify(t))}}function storageSaveTasksCount(e){e&&Array.isArray(e)&&(e=e.filter(e=>e.taskMeta)?.length,localStorage.setItem("spotfix_tasks_count",""+e))}function storageCheckTaskUpdate(e,t){if(!e||!t)return null;let a={};try{a=JSON.parse(localStorage.getItem("spotfix_task_updates")||"{}")}catch(e){a={}}e=a[e];return!!e&&new Date(e.taskLastUpdate)e!==a),localStorage.setItem("spotfix_unread_updates",JSON.stringify(t))}}function storageTasksHasUnreadUpdates(){let t=[];try{t=JSON.parse(localStorage.getItem("spotfix_unread_updates")||"[]")}catch(e){t=[]}return 0this.handleFileInputChange(e))}bindPaperClipAction(e){e.addEventListener("click",e=>{e.preventDefault(),this.fileInput&&this.fileInput.click()})}handleFileInputChange(e){this.clearError();var t=Array.from(e.target.files);this.files.length+t.length>this.maxFiles?this.showError(`Maximum ${this.maxFiles} files can be attached.`):(t.filter(e=>this.validateFile(e)).forEach(e=>this.addFile(e)),e.target.value="",this.uploaderWrapper.style.display="block")}validateFile(e){return e.size>this.maxFileSize?(this.showError(`File "${e.name}" is too large. Maximum size: `+this.formatFileSize(this.maxFileSize)),!1):this.getTotalSize()+e.size>this.maxTotalSize?(this.showError("Total files size exceeded. Maximum: "+this.formatFileSize(this.maxTotalSize)),!1):!(0e+t.file.size,0)}addFile(e){e={id:this.generateFileId(),file:e};this.files.push(e),this.renderFileList()}generateFileId(){return Date.now()+Math.random().toString(36).substr(2,9)}removeFile(t){this.files=this.files.filter(e=>e.id!==t),this.renderFileList(),this.clearError()}renderFileList(){var e;this.fileList&&(0===this.files.length?this.fileList.innerHTML=ksesFilter('No files attached
'):(e=this.files.map(e=>this.createFileItem(e)),this.fileList.innerHTML=ksesFilter(""),e.forEach(e=>this.fileList.appendChild(e))))}createFileItem(e){let{file:t,id:a}=e;e=document.createElement("div");return e.className="doboard_task_widget__file-upload__file-item",e.innerHTML=ksesFilter(`
@@ -260,6 +294,38 @@ let INDEXED_DB_NAME="spotfix-localDB",indexedDBVersion=1,TABLE_USERS="users",TAB
Log out
+
+
+
+
@@ -269,6 +335,10 @@ let INDEXED_DB_NAME="spotfix-localDB",indexedDBVersion=1,TABLE_USERS="users",TAB
doBoard
+
`}static wrap(){return`
diff --git a/dist/doboard-widget-bundle.min.js.map b/dist/doboard-widget-bundle.min.js.map
index 5b1a8ca..7832ad9 100644
--- a/dist/doboard-widget-bundle.min.js.map
+++ b/dist/doboard-widget-bundle.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"doboard-widget-bundle.min.js","sources":["doboard-widget-bundle.js"],"sourcesContent":["const INDEXED_DB_NAME = 'spotfix-localDB';\r\nconst indexedDBVersion = 1;\r\n\r\nconst TABLE_USERS = 'users';\r\nconst TABLE_TASKS = 'tasks';\r\nconst TABLE_COMMENTS = 'comments';\r\n\r\nconst LOCAL_DATA_BASE_TABLE = [\r\n {name: TABLE_USERS, keyPath: 'user_id'},\r\n {name: TABLE_TASKS, keyPath: 'taskId'},\r\n {name: TABLE_COMMENTS, keyPath: 'commentId'},\r\n];\r\n\r\nasync function openIndexedDB(name, version = indexedDBVersion) {\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(name, version);\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(request.error);\r\n request.onupgradeneeded = (e) => resolve(request.result);\r\n });\r\n}\r\n\r\nasync function deleteDB() {\r\n try {\r\n const dbs = await window.indexedDB.databases();\r\n for (const db of dbs) {\r\n await new Promise((resolve) => {\r\n const deleteReq = indexedDB.deleteDatabase(db.name);\r\n deleteReq.onsuccess = () => resolve();\r\n deleteReq.onerror = () => resolve();\r\n });\r\n }\r\n } catch (err) {\r\n console.warn('deleteDB error', err);\r\n }\r\n}\r\n\r\nconst spotfixIndexedDB = {\r\n getIndexedDBName: () =>\r\n `${INDEXED_DB_NAME}_${localStorage.getItem('spotfix_session_id') || localStorage.getItem('spotfix_project_token')}`,\r\n\r\n error: (request, error) => {\r\n console.error('IndexedDB error', request, error);\r\n },\r\n\r\n init: async () => {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n const projectToken = localStorage.getItem('spotfix_project_token');\r\n\r\n if (!sessionId && !projectToken) return { needInit: false };\r\n\r\n const dbName = spotfixIndexedDB.getIndexedDBName();\r\n\r\n await deleteDB();\r\n\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(dbName, indexedDBVersion);\r\n\r\n request.onupgradeneeded = (e) => {\r\n const db = e.target.result;\r\n LOCAL_DATA_BASE_TABLE.forEach((item) => {\r\n if (!db.objectStoreNames.contains(item.name)) {\r\n const store = db.createObjectStore(item.name, { keyPath: item.keyPath });\r\n if (item.name === TABLE_COMMENTS) store.createIndex('taskId', 'taskId');\r\n if (item.name === TABLE_TASKS) store.createIndex('userId', 'userId');\r\n }\r\n });\r\n resolve({ needInit: true });\r\n };\r\n\r\n request.onsuccess = (e) => {\r\n const db = e.target.result;\r\n const missingStores = LOCAL_DATA_BASE_TABLE.filter(\r\n (item) => !db.objectStoreNames.contains(item.name)\r\n );\r\n\r\n if (missingStores.length === 0) {\r\n db.close();\r\n resolve({ needInit: true });\r\n } else {\r\n const newVersion = db.version + 1;\r\n db.close();\r\n const upgradeRequest = indexedDB.open(dbName, newVersion);\r\n upgradeRequest.onupgradeneeded = (e2) => {\r\n const db2 = e2.target.result;\r\n missingStores.forEach((item) => {\r\n const store = db2.createObjectStore(item.name, { keyPath: item.keyPath });\r\n if (item.name === TABLE_COMMENTS) store.createIndex('taskId', 'taskId');\r\n if (item.name === TABLE_TASKS) store.createIndex('userId', 'userId');\r\n });\r\n };\r\n upgradeRequest.onsuccess = () => resolve({ needInit: true });\r\n upgradeRequest.onerror = (err) => reject(err);\r\n }\r\n };\r\n\r\n request.onerror = (err) => reject(err);\r\n });\r\n },\r\n\r\n withStore: async (table, mode = 'readwrite', callback) => {\r\n const dbName = spotfixIndexedDB.getIndexedDBName();\r\n const db = await openIndexedDB(dbName, indexedDBVersion);\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const transaction = db.transaction(table, mode);\r\n const store = transaction.objectStore(table);\r\n\r\n const result = callback(store);\r\n\r\n transaction.oncomplete = () => {\r\n db.close();\r\n resolve(result);\r\n };\r\n transaction.onerror = (e) => {\r\n db.close();\r\n reject(e.target.error);\r\n };\r\n } catch (err) {\r\n db.close();\r\n reject(err);\r\n }\r\n });\r\n },\r\n\r\n put: async (table, data) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => {\r\n if (Array.isArray(data)) {\r\n data.forEach((item) => store.put(item));\r\n } else {\r\n store.put(data);\r\n }\r\n });\r\n },\r\n\r\n delete: async (table, key) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => {\r\n store.delete(key);\r\n });\r\n },\r\n\r\n clearTable: async (table) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => store.clear());\r\n },\r\n\r\n clearPut: async (table, data) => {\r\n await spotfixIndexedDB.clearTable(table);\r\n await spotfixIndexedDB.put(table, data);\r\n },\r\n\r\n getAll: async (table, indexName, value) => {\r\n return spotfixIndexedDB.withStore(table, 'readonly', (store) => {\r\n return new Promise((resolve, reject) => {\r\n let request;\r\n if (indexName && value !== undefined) {\r\n request = store.index(indexName).getAll(value);\r\n } else {\r\n request = store.getAll();\r\n }\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(request.error);\r\n });\r\n });\r\n },\r\n\r\n getTable: async (table) => {\r\n if (!localStorage.getItem('spotfix_session_id') && !localStorage.getItem('spotfix_project_token')) return [];\r\n return spotfixIndexedDB.getAll(table);\r\n },\r\n\r\n deleteTable: async (table, key) => {\r\n return spotfixIndexedDB.delete(table, key);\r\n },\r\n};\r\n\nconst SPOTFIX_DOBOARD_API_URL = 'https://api.doboard.com';\r\n\r\n/**\r\n * Makes an API call to the DoBoard endpoint with form data\r\n *\r\n * @param {Object} data - The data to send in the request\r\n * @param {string} method - The API method to call\r\n * @param {string|number} accountId - Optional account ID for the endpoint\r\n *\r\n * @returns {Promise
} The response data when operation_status is 'SUCCESS'\r\n */\r\nconst spotfixApiCall = async(data, method, accountId = undefined) => {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Data must be a valid object');\r\n }\r\n\r\n if (!method || typeof method !== 'string') {\r\n throw new Error('Method must be a valid string');\r\n }\r\n\r\n if (accountId !== undefined && (typeof accountId !== 'string' && typeof accountId !== 'number')) {\r\n throw new Error('AccountId must be a string or number');\r\n }\r\n\r\n const formData = new FormData();\r\n for (const key in data) {\r\n if (data.hasOwnProperty(key)) {\r\n if (data[key] !== undefined && data[key] !== null) {\r\n formData.append(key, data[key]);\r\n }\r\n }\r\n }\r\n\r\n let endpointUrl;\r\n if (accountId !== undefined) {\r\n endpointUrl = `${SPOTFIX_DOBOARD_API_URL}/${accountId}/${method}`;\r\n } else {\r\n endpointUrl = `${SPOTFIX_DOBOARD_API_URL}/${method}`;\r\n }\r\n\r\n try {\r\n new URL(endpointUrl);\r\n } catch (error) {\r\n throw new Error(`Invalid endpoint URL: ${endpointUrl}`);\r\n }\r\n\r\n let response;\r\n try {\r\n response = await fetch(endpointUrl, {\r\n method: 'POST',\r\n body: formData,\r\n });\r\n } catch (networkError) {\r\n throw new Error(`Network error: ${networkError.message}`);\r\n }\r\n\r\n let responseBody;\r\n try {\r\n responseBody = await response.json();\r\n } catch (parseError) {\r\n throw new Error('Failed to parse JSON response from server');\r\n }\r\n\r\n if (!responseBody || typeof responseBody !== 'object') {\r\n throw new Error('Invalid response format from server');\r\n }\r\n\r\n if (!responseBody.data) {\r\n throw new Error('Missing data field in server response');\r\n }\r\n\r\n if (!responseBody.data.operation_status) {\r\n throw new Error('Missing operation_status in response data');\r\n }\r\n\r\n if (responseBody.data.operation_status === 'FAILED') {\r\n const errorMessage = responseBody.data.operation_message || 'Operation failed without specific message';\r\n throw new Error(errorMessage);\r\n }\r\n\r\n if (responseBody.data.operation_status === 'SUCCESS') {\r\n return responseBody.data;\r\n }\r\n\r\n throw new Error(`Unknown operation status: ${responseBody.data.operation_status}`);\r\n}\r\n\r\nconst userConfirmEmailDoboard = async (emailConfirmationToken) => {\r\n const data = {\r\n email_confirmation_token: encodeURIComponent(emailConfirmationToken)\r\n }\r\n const result = await spotfixApiCall(data, 'user_confirm_email');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accounts: result.accounts,\r\n operationStatus: result.operation_status\r\n };\r\n};\r\n\r\nconst createTaskDoboard = async (sessionId, taskDetails) => {\r\n const accountId = taskDetails.accountId;\r\n const data = {\r\n session_id: sessionId,\r\n project_token: taskDetails.projectToken,\r\n project_id: taskDetails.projectId,\r\n user_id: localStorage.getItem('spotfix_user_id'),\r\n name: taskDetails.taskTitle,\r\n comment: taskDetails.taskDescription,\r\n meta: taskDetails.taskMeta,\r\n task_type: 'PUBLIC'\r\n }\r\n const result = await spotfixApiCall(data, 'task_add', accountId);\r\n return {\r\n taskId: result.task_id,\r\n }\r\n};\r\n\r\nconst createTaskCommentDoboard = async (accountId, sessionId, taskId, comment, projectToken, status = 'ACTIVE') => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n task_id: taskId,\r\n comment: comment,\r\n status: status\r\n }\r\n const result = await spotfixApiCall(data, 'comment_add', accountId);\r\n return {\r\n commentId: result.comment_id,\r\n };\r\n};\r\n\r\nconst attachmentAddDoboard = async (fileData) => {\r\n const accountId = fileData.params.accountId;\r\n const data = {\r\n session_id: fileData.sessionId,\r\n project_token: fileData.params.projectToken,\r\n account_id: fileData.params.accountId,\r\n comment_id: fileData.commentId,\r\n filename: fileData.fileName,\r\n file: fileData.fileBinary,\r\n attachment_order: fileData.attachmentOrder\r\n }\r\n const result = await spotfixApiCall(data, 'attachment_add', accountId);\r\n // @ToDo need to handle result?\r\n};\r\n\r\nconst registerUserDoboard = async (projectToken, accountId, email, nickname, pageURL) => {\r\n let data = {\r\n project_token: projectToken,\r\n account_id: accountId,\r\n confirmation_url: email,\r\n }\r\n if (email && nickname) {\r\n data.email = email;\r\n data.name = nickname;\r\n }\r\n\r\n if (localStorage.getItem('bot_detector_event_token')) {\r\n try {\r\n const botDetectorData = JSON.parse(localStorage.getItem('bot_detector_event_token'));\r\n if (botDetectorData?.value) {\r\n data.bot_detector_event_token = botDetectorData?.value;\r\n }\r\n } catch (error) {\r\n data.bot_detector_event_token = '';\r\n }\r\n }\r\n const result = await spotfixApiCall(data, 'user_registration');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accountExists: result.user_email_confirmed === 1,\r\n operationMessage: result.operation_message,\r\n operationStatus: result.operation_status,\r\n userEmailConfirmed: result.user_email_confirmed,\r\n };\r\n};\r\n\r\nconst loginUserDoboard = async (email, password) => {\r\n const data = {\r\n email: email,\r\n password: password,\r\n }\r\n const result = await spotfixApiCall(data, 'user_authorize');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accountExists: result.user_email_confirmed === 1,\r\n operationMessage: result.operation_message,\r\n operationStatus: result.operation_status,\r\n userEmailConfirmed: result.user_email_confirmed,\r\n }\r\n}\r\n\r\nconst logoutUserDoboard = async (projectToken, accountId) => {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n if(sessionId && accountId) {\r\n const data = {\r\n session_id: sessionId,\r\n };\r\n\r\n const email = localStorage.getItem('spotfix_email') || '';\r\n\r\n if (email && email.includes('spotfix_')) {\r\n data.project_token = projectToken;\r\n }\r\n\r\n const result = await spotfixApiCall(data, 'user_unauthorize', accountId);\r\n\r\n if (result.operation_status === 'SUCCESS') {\r\n await deleteDB();\r\n clearLocalstorageOnLogout();\r\n }\r\n }\r\n}\r\n\r\nconst getTasksDoboard = async (projectToken, sessionId, accountId, projectId, userId) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n project_id: projectId,\r\n task_type: 'PUBLIC',\r\n status: 'ACTIVE,DONE',\r\n }\r\n if ( userId ) {\r\n data.user_id = userId;\r\n }\r\n const result = await spotfixApiCall(data, 'task_get', accountId);\r\n const tasks = result.tasks.map(task => ({\r\n taskId: task.task_id,\r\n taskTitle: task.name,\r\n userId: task.user_id,\r\n taskLastUpdate: task.updated,\r\n taskCreated: task.created,\r\n taskCreatorTaskUser: task.creator_user_id,\r\n taskMeta: task.meta,\r\n taskStatus: task.status,\r\n }));\r\n await spotfixIndexedDB.clearPut(TABLE_TASKS, tasks);\r\n storageSaveTasksCount(tasks);\r\n return tasks;\r\n}\r\n\r\n\r\nconst getTasksCommentsDoboard = async (sessionId, accountId, projectToken, status = 'ACTIVE') => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n status: status\r\n }\r\n const result = await spotfixApiCall(data, 'comment_get', accountId);\r\n const comments = result.comments.map(comment => ({\r\n taskId: comment.task_id,\r\n commentId: comment.comment_id,\r\n userId: comment.user_id,\r\n commentBody: comment.comment,\r\n commentDate: comment.updated,\r\n status: comment.status,\r\n issueTitle: comment.task_name,\r\n }));\r\n await spotfixIndexedDB.clearPut(TABLE_COMMENTS, comments);\r\n return comments;\r\n};\r\n\r\nconst getUserDoboard = async (sessionId, projectToken, accountId, userId) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n }\r\n if (userId) data.user_id = userId;\r\n\r\n const result = await spotfixApiCall(data, 'user_get', accountId);\r\n if (data.user_id) {\r\n await spotfixIndexedDB.put(TABLE_USERS, result.users);\r\n } else {\r\n await spotfixIndexedDB.clearPut(TABLE_USERS, result.users);\r\n }\r\n return result.users;\r\n\r\n // @ToDo Need to handle these two different answers?\r\n /*// Format 1: users inside data\r\n if (responseBody.data && responseBody.data.operation_status) {\r\n if (responseBody.data.operation_status === 'FAILED') {\r\n throw new Error(responseBody.data.operation_message);\r\n }\r\n if (responseBody.data.operation_status === 'SUCCESS') {\r\n if (Array.isArray(responseBody.data.users)) {\r\n return responseBody.data.users;\r\n }\r\n return [];\r\n }\r\n }\r\n // Format 2: users at the top level\r\n if (responseBody.operation_status) {\r\n if (responseBody.operation_status === 'FAILED') {\r\n throw new Error(responseBody.operation_message);\r\n }\r\n if (responseBody.operation_status === 'SUCCESS') {\r\n if (Array.isArray(responseBody.users)) {\r\n return responseBody.users;\r\n }\r\n return [];\r\n }\r\n }*/\r\n};\r\n\r\nconst userUpdateDoboard = async (projectToken, accountId, sessionId, userId, timezone) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n user_id: userId,\r\n timestamp: timezone\r\n }\r\n await spotfixApiCall(data, 'user_update', accountId);\r\n return {\r\n success: true\r\n };\r\n}\r\n\r\nconst getReleaseVersion = async () => {\r\n try {\r\n const res = await fetch('https://api.github.com/repos/CleanTalk/SpotFix/releases');\r\n const data = await res.json();\r\n\r\n if (data.length > 0 && data[0].tag_name) {\r\n storageSaveSpotfixVersion(data[0].tag_name);\r\n return data[0].tag_name;\r\n }\r\n\r\n return null;\r\n } catch (err) {\r\n return null;\r\n }\r\n};\r\n\r\n\nlet socket = null;\r\nlet heartbeatInterval = null;\r\n\r\nconst WS_URL = 'wss://ws.doboard.com';\r\n\r\nconst getSessionId = () => localStorage.getItem('spotfix_session_id');\r\n\r\nconst buildMessage = (action) => ({\r\n channel: `account:${localStorage.getItem('spotfix_company_id')}`,\r\n action,\r\n account_id: localStorage.getItem('spotfix_company_id'),\r\n session_id: getSessionId(),\r\n project_token: localStorage.getItem('spotfix_project_token'),\r\n});\r\n\r\nconst wsSpotfix = {\r\n connect() {\r\n if ((socket && socket.readyState === WebSocket.OPEN) || !getSessionId()) {\r\n return;\r\n }\r\n\r\n socket = new WebSocket(WS_URL);\r\n\r\n socket.onopen = () => {\r\n heartbeatInterval = setInterval(() => {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n socket.send('heartbeat');\r\n }\r\n }, 50 * 1000);\r\n wsSpotfix.send(buildMessage('SUBSCRIBE'));\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n if (event.data === 'heartbeat') {\r\n return;\r\n }\r\n\r\n try {\r\n const data = JSON.parse(event.data);\r\n\r\n switch (data.object) {\r\n case 'users':\r\n spotfixIndexedDB.put(TABLE_USERS, data.data);\r\n break;\r\n case 'tasks':\r\n if (data.data.status === 'REMOVED') {\r\n spotfixIndexedDB.delete(TABLE_TASKS, data.data.task_id);\r\n break;\r\n }\r\n spotfixIndexedDB.put(TABLE_TASKS, {\r\n taskId: data.data.task_id,\r\n taskTitle: data.data.name,\r\n userId: data.data.user_id,\r\n taskLastUpdate: data.data.updated,\r\n taskCreated: data.data.created,\r\n taskCreatorTaskUser: data.data.creator_user_id,\r\n taskMeta: data.data.meta,\r\n taskStatus: data.data.status,\r\n });\r\n break;\r\n\r\n case 'comments':\r\n if (data.data.status === 'REMOVED') {\r\n spotfixIndexedDB.delete(TABLE_COMMENTS, data.data.comment_id);\r\n break;\r\n }\r\n spotfixIndexedDB.put(TABLE_COMMENTS, {\r\n taskId: data.data.task_id,\r\n commentId: data.data.comment_id,\r\n userId: data.data.user_id,\r\n commentBody: data.data.comment,\r\n commentDate: data.data.updated,\r\n status: data.data.status,\r\n issueTitle: data.data.task_name,\r\n });\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n } catch (e) {\r\n console.warn('WS non-JSON message:', event.data);\r\n }\r\n };\r\n\r\n socket.onclose = (e) => {\r\n console.warn('WS closed:', e.code, e.reason);\r\n\r\n socket = null;\r\n\r\n if (heartbeatInterval) {\r\n clearInterval(heartbeatInterval);\r\n heartbeatInterval = null;\r\n }\r\n };\r\n\r\n socket.onerror = (e) => {\r\n console.error('WS error:', e);\r\n };\r\n },\r\n\r\n send(data) {\r\n if (!socket || socket.readyState !== WebSocket.OPEN) {\r\n console.warn('WebSocket is not connected');\r\n return;\r\n }\r\n socket.send(JSON.stringify(data));\r\n },\r\n\r\n close() {\r\n wsSpotfix.unsubscribe();\r\n socket?.close();\r\n },\r\n\r\n subscribe() {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n wsSpotfix.send(buildMessage('SUBSCRIBE'));\r\n }\r\n },\r\n\r\n unsubscribe() {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n wsSpotfix.send(buildMessage('UNSUBSCRIBE'));\r\n }\r\n },\r\n};\r\n\nconst SPOTFIX_VERSION = \"1.1.5\";\r\n\n\r\nasync function confirmUserEmail(emailConfirmationToken, params) {\r\n\tconst result = await userConfirmEmailDoboard(emailConfirmationToken);\r\n\t// Save session data to LS\r\n\tlocalStorage.setItem('spotfix_email', result.email);\r\n\tlocalStorage.setItem('spotfix_session_id', result.sessionId);\r\n\tlocalStorage.setItem('spotfix_user_id', result.userId);\r\n\tawait spotfixIndexedDB.init();\r\n\r\n\t// Get pending task from LS\r\n\tconst pendingTaskRaw = localStorage.getItem('spotfix_pending_task');\r\n\tif (!pendingTaskRaw) throw new Error('No pending task data');\r\n\r\n\tlet pendingTask;\r\n\ttry {\r\n\t\tpendingTask = JSON.parse(pendingTaskRaw);\r\n\t} catch (error) {\r\n\t\tthrow new Error('Invalid pending task data');\r\n\t}\r\n\r\n\t// Form taskDetails for task creation\r\n\tconst taskDetails = {\r\n\t\ttaskTitle: pendingTask.selectedText || 'New Task',\r\n\t\ttaskDescription: pendingTask.description || '',\r\n\t\tselectedData: pendingTask,\r\n\t\tprojectToken: params.projectToken,\r\n\t\tprojectId: params.projectId,\r\n\t\taccountId: params.accountId,\r\n\t\ttaskMeta: JSON.stringify(pendingTask)\r\n\t};\r\n\r\n\t// Create task\r\n\tconst createdTask = await handleCreateTask(result.sessionId, taskDetails);\r\n\t// Clear pending task\r\n\tlocalStorage.removeItem('spotfix_pending_task');\r\n\r\n\t// Return created task\r\n\treturn createdTask;\r\n}\r\n\r\nasync function getTasksFullDetails(params, tasks, currentActiveTaskId) {\r\n if (tasks.length > 0) {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\t\tawait getTasksCommentsDoboard(sessionId, params.accountId, params.projectToken);\r\n const comments = await spotfixIndexedDB.getAll(TABLE_COMMENTS);\r\n await getUserDoboard(sessionId, params.projectToken, params.accountId);\r\n\t\tconst users = await spotfixIndexedDB.getAll(TABLE_USERS);\r\n\t\tconst foundTask = tasks.find(item => +item.taskId === +currentActiveTaskId);\r\n\r\n return {\r\n comments: comments,\r\n users: users,\r\n\t\t\ttaskStatus: foundTask?.taskStatus,\r\n };\r\n }\r\n}\r\n\r\nasync function getUserDetails(params) {\r\n\t\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\t\tconst currentUserId = localStorage.getItem('spotfix_user_id');\r\n\t\tif(currentUserId) {\r\n\t\t\tawait getUserDoboard(sessionId, params.projectToken, params.accountId, currentUserId);\r\n\t\t\tconst users = await spotfixIndexedDB.getAll(TABLE_USERS);\r\n\t\t\treturn users.find(user => +user.user_id === +currentUserId) || {};\r\n\t\t}\r\n}\r\n\r\nasync function handleCreateTask(sessionId, taskDetails) {\r\n\ttry {\r\n\t\tconst result = await createTaskDoboard(sessionId, taskDetails);\r\n\t\tif (result && result.taskId && taskDetails.taskDescription) {\r\n const sign = `The spot has been posted at the following URL ${window.location.href} `;\r\n\t\t\tawait addTaskComment({\r\n\t\t\t\tprojectToken: taskDetails.projectToken,\r\n\t\t\t\taccountId: taskDetails.accountId\r\n\t\t\t}, result.taskId, taskDetails.taskDescription+sign);\r\n\t\t}\r\n\t\treturn result;\r\n\t} catch (err) {\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nasync function addTaskComment(params, taskId, commentText) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tif (!sessionId) throw new Error('No session');\r\n\tif (!params.projectToken || !params.accountId) throw new Error('Missing params');\r\n\treturn await createTaskCommentDoboard(params.accountId, sessionId, taskId, commentText, params.projectToken);\r\n}\r\n\r\nasync function getUserTasks(params) {\r\n\tif (!localStorage.getItem('spotfix_session_id')) {\r\n\t\treturn {};\r\n\t}\r\n\tconst projectToken = params.projectToken;\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst userId = localStorage.getItem('spotfix_user_id');\r\n\tawait getTasksDoboard(projectToken, sessionId, params.accountId, params.projectId, userId);\r\n\treturn await spotfixIndexedDB.getAll(TABLE_TASKS, 'userId', userId);\r\n}\r\n\r\nasync function getAllTasks(params) {\r\n\tif (!localStorage.getItem('spotfix_session_id')) {\r\n\t\treturn {};\r\n\t}\r\n\tconst projectToken = params.projectToken;\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tawait getTasksDoboard(projectToken, sessionId, params.accountId, params.projectId);\r\n\tconst tasksData = await spotfixIndexedDB.getAll(TABLE_TASKS);\r\n // Get only tasks with metadata\r\n\tconst filteredTaskData = tasksData.filter(task => {\r\n return task.taskMeta;\r\n });\r\n\r\n return filteredTaskData;\r\n}\r\n\r\nfunction formatDate(dateStr) {\r\n\t const months = [\r\n\t \t\"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\r\n\t \t\"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\r\n\t ];\r\n\t // dateStr expected format: 'YYYY-MM-DD HH:mm:ss' or 'YYYY-MM-DDTHH:mm:ssZ'\r\n\t if (!dateStr) return { date: '', time: '' };\r\n\t let dateObj;\r\n\t if (dateStr.includes('T')) {\r\n\t dateObj = new Date(dateStr);\r\n\t } else if (dateStr.includes(' ')) {\r\n\t dateObj = new Date(dateStr.replace(' ', 'T'));\r\n\t } else {\r\n\t dateObj = new Date(dateStr);\r\n\t }\r\n\t if (isNaN(dateObj.getTime())) return { date: '', time: '' };\r\n\r\n\t // Adjust to local timezone\r\n\t const offsetMinutes = dateObj.getTimezoneOffset();\r\n\t let localDateObj = new Date(dateObj.getTime() - offsetMinutes * 60000);\r\n\r\n\t const month = months[localDateObj.getMonth()];\r\n\t const day = localDateObj.getDate();\r\n\t const date = `${month} ${day}`;\r\n\t const hours = localDateObj.getHours().toString().padStart(2, '0');\r\n\t const minutes = localDateObj.getMinutes().toString().padStart(2, '0');\r\n\t const time = `${hours}:${minutes}`;\r\n\t return { date, time };\r\n}\r\n\r\nfunction getTaskAuthorDetails(params, taskId) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst mockUsersData =\r\n\t\t[\r\n\t\t\t{\r\n\t\t\t\t'taskId': '1',\r\n\t\t\t\t'taskAuthorAvatarImgSrc': 'https://s3.eu-central-1.amazonaws.com/cleantalk-ctask-atts/accounts/1/avatars/081a1b65d20fe318/m.jpg',\r\n\t\t\t\t'taskAuthorName': 'Test All Issues Single Author Name'\r\n\t\t\t}\r\n\t\t]\r\n\r\n\tconst defaultData =\r\n\t\t{\r\n\t\t\t'taskId': null,\r\n\t\t\t'taskAuthorAvatarImgSrc': null,\r\n\t\t\t'taskAuthorName': 'Task Author'\r\n\t\t};\r\n\r\n\tconst data = mockUsersData.find((element) => element.taskId === taskId);\r\n\treturn data === undefined ? defaultData : data;\r\n}\r\n\r\nfunction getIssuesCounterString(onPageSpotsCount, totalSpotsCount) {\r\n\treturn ` (${onPageSpotsCount}/${totalSpotsCount})`;\r\n}\r\n\r\n// Get the author's avatar\r\nfunction getAvatarSrc(author) {\r\n\tif (author && author.avatar) {\r\n\t\tif (typeof author.avatar === 'object' && author.avatar.m) {\r\n\t\t\treturn author.avatar.m;\r\n\t\t} else if (typeof author.avatar === 'string') {\r\n\t\t\treturn author.avatar;\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n}\r\n\r\n// Get the author's name\r\nfunction getAuthorName(author) {\r\n\tif (author) {\r\n\t\tif (author.name && author.name.trim().length > 0) {\r\n\t\t\treturn author.name;\r\n\t\t} else if (author.email && author.email.trim().length > 0) {\r\n\t\t\treturn author.email;\r\n\t\t}\r\n\t}\r\n\treturn 'Unknown Author';\r\n}\r\n\r\nfunction registerUser(taskDetails) {\r\n\tconst userEmail = taskDetails.userEmail;\r\n\tconst userName = taskDetails.userName;\r\n\tconst projectToken = taskDetails.projectToken;\r\n\tconst accountId = taskDetails.accountId;\r\n\tconst pageURL = taskDetails.selectedData.pageURL ? taskDetails.selectedData.pageURL : window.location.href;\r\n\r\n\tconst resultRegisterUser = (showMessageCallback) => registerUserDoboard(projectToken, accountId, userEmail, userName, pageURL)\r\n\t\t.then(response => {\r\n\t\t\tif (response.accountExists) {\r\n\t\t\t\tdocument.querySelector(\".doboard_task_widget-accordion>.doboard_task_widget-input-container\").innerText = ksesFilter('Account already exists. Please, login usin your password.');\r\n\t\t\t\tdocument.querySelector(\".doboard_task_widget-accordion>.doboard_task_widget-input-container.hidden\").classList.remove('hidden');\r\n\t\t\t\tdocument.getElementById(\"doboard_task_widget-user_password\").focus();\r\n\t\t\t} else if (response.sessionId) {\r\n\t\t\t\tlocalStorage.setItem('spotfix_session_id', response.sessionId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_user_id', response.userId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_email', response.email);\r\n\t\t\t\tspotfixIndexedDB.init();\r\n\t\t\t\tuserUpdate(projectToken, accountId);\r\n\t\t\t} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {\r\n\t\t\t\tif (response.operationMessage == 'Waiting for email confirmation') {\r\n\t\t\t\t\tresponse.operationMessage = 'Waiting for an email confirmation. Please check your Inbox.';\r\n\t\t\t\t}\r\n\t\t\t\tif (typeof showMessageCallback === 'function') {\r\n\t\t\t\t\tshowMessageCallback(response.operationMessage, 'notice');\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Session ID not found in response');\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tthrow error;\r\n\t\t});\r\n\r\n\t\treturn resultRegisterUser;\r\n}\r\n\r\nfunction loginUser(taskDetails) {\r\n\tconst userEmail = taskDetails.userEmail;\r\n\tconst userPassword = taskDetails.userPassword;\r\n\r\n\treturn (showMessageCallback) => loginUserDoboard(userEmail, userPassword)\r\n\t\t.then(response => {\r\n\t\t\tif (response.sessionId) {\r\n\t\t\t\tlocalStorage.setItem('spotfix_session_id', response.sessionId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_user_id', response.userId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_email', userEmail);\r\n\t\t\t\tspotfixIndexedDB.init();\r\n\t\t\t} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {\r\n\t\t\t\tif (typeof showMessageCallback === 'function') {\r\n\t\t\t\t\tshowMessageCallback(response.operationMessage, 'notice');\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Session ID not found in response');\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tthrow error;\r\n\t\t});\r\n}\r\n\r\nfunction userUpdate(projectToken, accountId) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst userId = localStorage.getItem('spotfix_user_id');\r\n\tconst timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\r\n\r\n\treturn userUpdateDoboard(projectToken, accountId, sessionId, userId, timezone);\r\n}\r\n\r\nfunction spotFixSplitUrl(url) {\r\n\ttry {\r\n\t\tif (!url || url.trim() === '') {\r\n\t\t\treturn '';\r\n\t\t}\r\n\t\tconst u = new URL(url);\r\n\t\tconst domain = u.host;\r\n\r\n\t\tconst segments = u.pathname.split('/').filter(Boolean);\r\n\r\n\t\tif (segments.length === 0) {\r\n\t\t\treturn domain;\r\n\t\t}\r\n\r\n\t\tconst reversed = segments.reverse();\r\n\t\treversed.push(domain);\r\n\t\treturn reversed.join(' / ');\r\n\t} catch (error) {\r\n\t\treturn '';\r\n\t}\r\n\r\n}\r\n\r\nfunction setToggleStatus(rootElement){\r\n\tconst clickHandler = () => {\r\n\t\tconst timer = setTimeout(() => {\r\n\t\t\tlocalStorage.setItem('spotfix_widget_is_closed', '1');\r\n\t\t\twsSpotfix.close();\r\n\t\t\trootElement.hide();\r\n\t\t\tclearTimeout(timer);\r\n\t\t}, 300);\r\n\t};\r\n\tconst toggle = document.getElementById('widget_visibility');\r\n\tif(toggle) {\r\n\t\ttoggle.checked = true;\r\n\t\ttoggle.addEventListener('click', clickHandler);\r\n\t}\r\n}\r\n\r\nfunction checkLogInOutButtonsVisible (){\r\n\tif(!localStorage.getItem('spotfix_session_id')) {\r\n\t\tconst el = document\r\n\t\t\t.getElementById('doboard_task_widget-user_menu-logout_button')\r\n\t\t\t?.closest('.doboard_task_widget-user_menu-item');\r\n\t\t\tif(el) el.style.display = 'none';\r\n\t} else {\r\n\t\tconst el = document.getElementById('doboard_task_widget-user_menu-signlog_button');\r\n\t\tif(el) el.style.display = 'none';\r\n\t}\r\n}\r\n\r\nfunction changeSize(container){\r\n\tif(container && +localStorage.getItem('maximize')){\r\n\t\tcontainer.classList.add('doboard_task_widget-container-maximize');\r\n\t} else if(container) {\r\n\t\tcontainer.classList.remove('doboard_task_widget-container-maximize');\r\n\t}\r\n}\r\n\nlet spotFixCSS = `.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:\"\";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:65px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login span{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active span{margin-bottom:24px}.doboard_task_widget-login span::after{position:absolute;top:0;right:4px;content:\"\";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active span::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:\"\";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:\"\";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:\"wght\" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url(\"data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E\") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E\") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:\"\"}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:\"\";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}`;\n/**\r\n * Widget class to create a task widget\r\n */\r\nclass CleanTalkWidgetDoboard {\r\n selectedText = '';\r\n selectedData = {};\r\n widgetElement = null;\r\n params = {};\r\n currentActiveTaskId = 0;\r\n savedIssuesQuantityOnPage = 0;\r\n savedIssuesQuantityAll = 0;\r\n allTasksData = {};\r\n srcVariables = {};\r\n\r\n /**\r\n * Constructor\r\n */\r\n constructor(selectedData, type) {\r\n this.selectedData = selectedData || '';\r\n this.selectedText = selectedData?.selectedText || '';\r\n this.srcVariables = {\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n iconEllipsesMore: SpotFixSVGLoader.getAsDataURI('iconEllipsesMore'),\r\n iconPlus: SpotFixSVGLoader.getAsDataURI('iconPlus'),\r\n iconMaximize: SpotFixSVGLoader.getAsDataURI('iconMaximize'),\r\n chevronBack: SpotFixSVGLoader.getAsDataURI('chevronBack'),\r\n buttonPaperClip: SpotFixSVGLoader.getAsDataURI('buttonPaperClip'),\r\n buttonSendMessage: SpotFixSVGLoader.getAsDataURI('buttonSendMessage'),\r\n logoDoBoardGreen: SpotFixSVGLoader.getAsDataURI('logoDoBoardGreen'),\r\n logoDoBoardWrap: SpotFixSVGLoader.getAsDataURI('logoDoBoardWrap'),\r\n iconSpotWidgetWrapPencil: SpotFixSVGLoader.getAsDataURI('iconSpotWidgetWrapPencil'),\r\n iconMarker: SpotFixSVGLoader.getAsDataURI('iconMarker'),\r\n iconSpotPublic: SpotFixSVGLoader.getAsDataURI('iconSpotPublic'),\r\n iconSpotPrivate: SpotFixSVGLoader.getAsDataURI('iconSpotPrivate'),\r\n iconLinkChain: SpotFixSVGLoader.getAsDataURI('iconLinkChain'),\r\n };\r\n this.fileUploader = new FileUploader(this.escapeHtml);\r\n this.init(type);\r\n }\r\n\r\n /**\r\n * Initialize the widget\r\n */\r\n async init(type) {\r\n this.params = this.getParams();\r\n\r\n // Check if email_confirmation_token is in URL\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const emailToken = urlParams.get('email_confirmation_token');\r\n if (emailToken) {\r\n try {\r\n // Confirm email and create task\r\n const createdTask = await confirmUserEmail(emailToken, this.params);\r\n this.allTasksData = await getAllTasks(this.params);\r\n // Open task interface\r\n this.currentActiveTaskId = createdTask.taskId;\r\n type = 'concrete_issue';\r\n storageSetWidgetIsClosed(false);\r\n // Clear email_confirmation_token from URL\r\n urlParams.delete('email_confirmation_token');\r\n const newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');\r\n window.history.replaceState({}, document.title, newUrl);\r\n } catch (err) {\r\n this.registrationShowMessage('Error confirming email: ' + err.message, 'error');\r\n }\r\n } else {\r\n // Load all tasks\r\n const isWidgetClosed = localStorage.getItem('spotfix_widget_is_closed');\r\n if((isWidgetClosed && !this.selectedText) || !isWidgetClosed){\r\n this.allTasksData = await getAllTasks(this.params);\r\n }\r\n }\r\n\r\n // Check if any task has updates\r\n let taskHasSiteOwnerUpdate;\r\n\r\n if (storageTasksHasUnreadUpdates()) {\r\n taskHasSiteOwnerUpdate = true;\r\n } else {\r\n if (type === 'wrap_review') {\r\n taskHasSiteOwnerUpdate = await checkIfTasksHasSiteOwnerUpdates(\r\n this.allTasksData,\r\n this.params\r\n );\r\n }\r\n }\r\n storageSaveTasksUpdateData(this.allTasksData);\r\n //check to hide on first run\r\n if (!storageWidgetCloseIsSet()) {\r\n storageSetWidgetIsClosed(true);\r\n }\r\n //check to show if any task has site owner updates\r\n if (taskHasSiteOwnerUpdate) {\r\n\r\n storageSetWidgetIsClosed(false);\r\n }\r\n this.widgetElement = await this.createWidgetElement(type);\r\n this.bindWidgetInputsInteractive();\r\n }\r\n\r\n getParams() {\r\n const script = document.querySelector(`script[src*=\"doboard-widget-bundle.\"]`);\r\n if ( ! script || ! script.src ) {\r\n throw new Error('Script not provided');\r\n }\r\n\r\n const url = new URL(script.src);\r\n let params = Object.fromEntries(url.searchParams.entries());\r\n if ( ! params ) {\r\n throw new Error('Script params not provided');\r\n }\r\n if ( ! params.projectToken || ! params.accountId || ! params.projectId ) {\r\n throw new Error('Necessary script params not provided');\r\n\r\n }\r\n if (params.accountId) {\r\n localStorage.setItem('spotfix_company_id', params.accountId);\r\n }\r\n if (params.projectToken) {\r\n localStorage.setItem('spotfix_project_token', params.projectToken);\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Binding events to create a task\r\n */\r\n bindCreateTaskEvents() {\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\r\n if (submitButton) {\r\n submitButton.addEventListener('click', async () => {\r\n // Check required fields: Report about and Description\r\n const taskTitleElement = document.getElementById('doboard_task_widget-title');\r\n const taskTitle = taskTitleElement.value;\r\n if ( ! taskTitle ) {\r\n taskTitleElement.style.borderColor = 'red';\r\n taskTitleElement.focus();\r\n taskTitleElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n const taskDescriptionElement = document.getElementById('doboard_task_widget-description')\r\n const taskDescription = taskDescriptionElement.value;\r\n if ( ! taskDescription ) {\r\n taskDescriptionElement.style.borderColor = 'red';\r\n taskDescriptionElement.focus();\r\n taskDescriptionElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n // If login section is open, check required fields: Nickname, Email\r\n let userName = '';\r\n let userEmail = '';\r\n let userPassword = '';\r\n const loginSectionElement = document.querySelector('.doboard_task_widget-login');\r\n\r\n if ( loginSectionElement && loginSectionElement.classList.contains('active') ) {\r\n const userEmailElement = document.getElementById('doboard_task_widget-user_email');\r\n const userNameElement = document.getElementById('doboard_task_widget-user_name');\r\n const userPasswordElement = document.getElementById('doboard_task_widget-user_password');\r\n\r\n userEmail = userEmailElement.value;\r\n if ( ! userEmail ) {\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n userEmailElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n // This is the registration request\r\n if ( userEmailElement && userNameElement ) {\r\n userName = userNameElement.value;\r\n if ( ! userName ) {\r\n userNameElement.style.borderColor = 'red';\r\n userNameElement.focus();\r\n userNameElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n }\r\n\r\n // This is the login request\r\n if ( userEmailElement && userPasswordElement && ! userNameElement ) {\r\n userPassword = userPasswordElement.value;\r\n if ( ! userPassword ) {\r\n userPasswordElement.style.borderColor = 'red';\r\n userPasswordElement.focus();\r\n userPasswordElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n }\r\n\r\n }\r\n\r\n // If it is the login request\r\n const userEmailElement = document.getElementById('doboard_task_widget-user_email');\r\n userEmail = userEmailElement.value;\r\n\r\n // Make the submit button disable with spinner\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n submitButton.disabled = true;\r\n submitButton.innerText = ksesFilter('Creating spot...');\r\n\r\n let taskDetails = {\r\n taskTitle: taskTitle,\r\n taskDescription: taskDescription,\r\n //typeSend: typeSend,\r\n selectedData: this.selectedData,\r\n projectToken: this.params.projectToken,\r\n projectId: this.params.projectId,\r\n accountId: this.params.accountId,\r\n taskMeta: JSON.stringify(this.selectedData ? this.selectedData : { pageURL: window.location.href }),\r\n };\r\n\r\n if ( userEmail ) {\r\n taskDetails.userEmail = userEmail\r\n }\r\n if ( userName ) {\r\n taskDetails.userName = userName\r\n }\r\n if ( userPassword ) {\r\n taskDetails.userPassword = userPassword\r\n }\r\n\r\n // Save pending task in LS\r\n localStorage.setItem('spotfix_pending_task', JSON.stringify({\r\n ...this.selectedData,\r\n description: taskDescription\r\n }));\r\n\r\n let submitTaskResult;\r\n try {\r\n submitTaskResult = await this.submitTask(taskDetails);\r\n } catch (error) {\r\n this.registrationShowMessage(error.message);\r\n return;\r\n }\r\n\r\n // Return the submit button normal state\r\n submitButton.disabled = false;\r\n submitButton.style.cursor = 'pointer';\r\n\r\n if ( submitTaskResult.needToLogin ) {\r\n // @ToDo Do not know what to de here: throw an error or pass log message?\r\n return;\r\n }\r\n\r\n if ( submitTaskResult.isPublic !== undefined ) {\r\n this.selectedData.isPublic = submitTaskResult.isPublic\r\n }\r\n\r\n // refersh tasks list after creation\r\n this.allTasksData = await getAllTasks(this.params);\r\n // save updates\r\n storageSaveTasksUpdateData(this.allTasksData);\r\n\r\n this.selectedData = {};\r\n await this.createWidgetElement('all_issues');\r\n storageSetWidgetIsClosed(false);\r\n hideContainersSpinner(false);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Create widget element\r\n * @return {HTMLElement} widget element\r\n */\r\n async createWidgetElement(type, showOnlyCurrentPage = false) {\r\n const widgetContainer = document.querySelector('.doboard_task_widget') ? document.querySelector('.doboard_task_widget') : document.createElement('div');\r\n widgetContainer.className = 'doboard_task_widget';\r\n widgetContainer.innerHTML = ksesFilter('');\r\n widgetContainer.removeAttribute('style');\r\n\r\n let templateName = '';\r\n let tasksFullDetails;\r\n\r\n let templateVariables = {};\r\n\r\n const config = window.SpotfixWidgetConfig;\r\n\r\n switch (type) {\r\n case 'create_issue':\r\n templateName = 'create_issue';\r\n this.type_name = templateName;\r\n templateVariables = {\r\n selectedText: this.selectedText,\r\n currentDomain: document.location.hostname || '',\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n iconMaximize: SpotFixSVGLoader.getAsDataURI('iconMaximize'),\r\n iconEllipsesMore: SpotFixSVGLoader.getAsDataURI('iconEllipsesMore'),\r\n ...this.srcVariables\r\n };\r\n storageGetUserIsDefined() && storageSetWidgetIsClosed(false);\r\n break;\r\n case 'wrap':\r\n if (storageGetWidgetIsClosed()) {\r\n return;\r\n }\r\n\r\n templateName = 'wrap';\r\n templateVariables = {position: !Number.isNaN(Number(config?.verticalPosition))\r\n ? `${Number(config?.verticalPosition)}vh` : '0vh', ...this.srcVariables};\r\n break;\r\n case 'wrap_review':\r\n templateName = 'wrap_review';\r\n templateVariables = {position: !Number.isNaN(Number(config?.verticalPosition))\r\n ? `${Number(config?.verticalPosition)}vh` : '0vh', ...this.srcVariables};\r\n break;\r\n case 'all_issues':\r\n templateName = 'all_issues';\r\n this.type_name = templateName;\r\n templateVariables = {...this.srcVariables};\r\n break;\r\n case 'user_menu':\r\n templateName = 'user_menu';\r\n const version = localStorage.getItem('spotfix_app_version') || SPOTFIX_VERSION;\r\n templateVariables = {\r\n spotfixVersion: version ? 'Spotfix version ' + version + '.' : '',\r\n avatar: SpotFixSVGLoader.getAsDataURI('iconAvatar'),\r\n iconEye: SpotFixSVGLoader.getAsDataURI('iconEye'),\r\n iconDoor: SpotFixSVGLoader.getAsDataURI('iconDoor'),\r\n chevronBackDark: SpotFixSVGLoader.getAsDataURI('chevronBackDark'),\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n userName: 'Guest',\r\n email: localStorage.getItem('spotfix_email') || '',\r\n ...this.srcVariables};\r\n break;\r\n case 'concrete_issue':\r\n templateName = 'concrete_issue';\r\n this.type_name = templateName;\r\n // Update the number of tasks\r\n this.savedIssuesQuantityAll = Array.isArray(this.allTasksData) ? this.allTasksData.length : 0;\r\n // Calculate the number of issues on the current page\r\n this.savedIssuesQuantityOnPage = Array.isArray(this.allTasksData)\r\n ? this.allTasksData.filter(task => {\r\n try {\r\n const meta = task.taskMeta ? JSON.parse(task.taskMeta) : {};\r\n return meta.pageURL === window.location.href;\r\n } catch (e) { return false; }\r\n }).length\r\n : 0;\r\n\r\n templateVariables = {\r\n issueTitle: '...',\r\n issueComments: [],\r\n issuesCounter: getIssuesCounterString(this.savedIssuesQuantityOnPage, this.savedIssuesQuantityAll),\r\n ...this.srcVariables,\r\n };\r\n break;\r\n default:\r\n break;\r\n }\r\n widgetContainer.innerHTML = this.loadTemplate(templateName, templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n\r\n // remove highlights before any screen called\r\n spotFixRemoveHighlights();\r\n const container = document.querySelector('.doboard_task_widget-container');\r\n switch (type) {\r\n case 'create_issue':\r\n\r\n if(container && +localStorage.getItem('maximize')){\r\n container.classList.add('doboard_task_widget-container-maximize');\r\n } else if(container) {\r\n container.classList.remove('doboard_task_widget-container-maximize');\r\n }\r\n // highlight selected item during task creation\r\n const selection = window.getSelection();\r\n const sessionIdExists = !!localStorage.getItem('spotfix_session_id');\r\n const email = localStorage.getItem('spotfix_email');\r\n\r\n if (sessionIdExists && email && !email.includes('spotfix_')) {\r\n document.querySelector('.doboard_task_widget-login').classList.add('hidden');\r\n }\r\n if (\r\n selection.type === 'Range'\r\n ) {\r\n const selectedData = spotFixGetSelectedData(selection);\r\n spotFixScrollToNodePath(selectedData.nodePath);\r\n this.positionWidgetContainer();\r\n }\r\n // bind creation events\r\n this.bindCreateTaskEvents();\r\n break;\r\n case 'wrap':\r\n await this.getTaskCount();\r\n document.querySelector('.doboard_task_widget-wrap').addEventListener('click', (e) => {\r\n const widgetElementClasses = e.currentTarget.classList;\r\n if (widgetElementClasses && !widgetElementClasses.contains('hidden')) {\r\n this.createWidgetElement('all_issues');\r\n }\r\n });\r\n hideContainersSpinner(false);\r\n break;\r\n case 'wrap_review':\r\n document.querySelector('#doboard_task_widget_button').addEventListener('click', (e) => {\r\n spotFixOpenWidget(this.selectedData, 'create_issue');\r\n });\r\n break;\r\n case 'all_issues':\r\n changeSize(container);\r\n\r\n spotFixRemoveHighlights();\r\n let issuesQuantityOnPage = 0;\r\n if (!this.allTasksData?.length) {\r\n this.allTasksData = await getAllTasks(this.params);\r\n }\r\n const tasks = this.allTasksData;\r\n tasksFullDetails = await getTasksFullDetails(this.params, tasks, this.currentActiveTaskId);\r\n let spotsToBeHighlighted = [];\r\n if (tasks.length > 0) {\r\n const currentURL = window.location.href;\r\n const sortedTasks = tasks.sort((a, b) => {\r\n const aIsHere = JSON.parse(a.taskMeta).pageURL === currentURL ? 1 : 0;\r\n const bIsHere = JSON.parse(b.taskMeta).pageURL === currentURL ? 1 : 0;\r\n return bIsHere - aIsHere;\r\n });\r\n\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML = '';\r\n\r\n for (let i = 0; i < sortedTasks.length; i++) {\r\n const elTask = sortedTasks[i];\r\n\r\n // Data from api\r\n const taskId = elTask.taskId;\r\n const taskTitle = elTask.taskTitle;\r\n const taskMetaString = elTask.taskMeta;\r\n let taskData = null;\r\n if (taskMetaString) {\r\n try {\r\n taskData = JSON.parse(taskMetaString);\r\n taskData.isFixed = elTask.taskStatus === 'DONE';\r\n taskData.taskId = elTask.taskId;\r\n } catch (error) {\r\n taskData = null;\r\n }\r\n }\r\n const currentPageURL = taskData ? taskData.pageURL : '';\r\n const taskNodePath = taskData ? taskData.nodePath : '';\r\n\r\n // Define publicity details\r\n let taskPublicStatusImgSrc = '';\r\n let taskPublicStatusHint = 'Task publicity is unknown'\r\n if (taskData && taskData.isPublic !== undefined) {\r\n if (taskData.isPublic) {\r\n taskPublicStatusImgSrc = this.srcVariables.iconSpotPublic;\r\n taskPublicStatusHint = 'The task is public';\r\n } else {\r\n taskPublicStatusImgSrc = this.srcVariables.iconSpotPrivate;\r\n taskPublicStatusHint = 'The task is private and visible only for registered DoBoard users';\r\n }\r\n }\r\n\r\n if(currentPageURL === window.location.href){\r\n issuesQuantityOnPage++;\r\n }\r\n\r\n if (!showOnlyCurrentPage || currentPageURL === window.location.href) {\r\n\r\n const taskFullDetails = getTaskFullDetails(tasksFullDetails, taskId)\r\n\r\n const avatarData = getAvatarData(taskFullDetails);\r\n const listIssuesTemplateVariables = {\r\n taskTitle: taskTitle || '',\r\n taskAuthorAvatarImgSrc: taskFullDetails.taskAuthorAvatarImgSrc,\r\n taskAuthorName: taskFullDetails.taskAuthorName,\r\n taskPublicStatusImgSrc: taskPublicStatusImgSrc,\r\n taskPublicStatusHint: taskPublicStatusHint,\r\n taskLastMessage: ksesFilter(taskFullDetails.lastMessageText),\r\n taskPageUrl: currentPageURL,\r\n iconLinkChain: this.srcVariables.iconLinkChain,\r\n taskFormattedPageUrl: spotFixSplitUrl(currentPageURL),\r\n taskLastUpdate: taskFullDetails.lastMessageTime,\r\n nodePath: this.sanitizeNodePath(taskNodePath),\r\n taskId: taskId,\r\n avatarCSSClass: avatarData.avatarCSSClass,\r\n avatarStyle: avatarData.avatarStyle,\r\n taskAuthorInitials: avatarData.taskAuthorInitials,\r\n initialsClass: avatarData.initialsClass,\r\n classUnread: '',\r\n elementBgCSSClass: elTask.taskStatus !== 'DONE' ? '' : 'doboard_task_widget-task_row-green',\r\n statusFixedHtml: elTask.taskStatus !== 'DONE' ? '' : this.loadTemplate('fixedHtml'),\r\n };\r\n\r\n const taskOwnerReplyIsUnread = storageProvidedTaskHasUnreadUpdates(taskFullDetails.taskId);\r\n if (taskOwnerReplyIsUnread) {\r\n listIssuesTemplateVariables.classUnread = 'unread';\r\n }\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML += this.loadTemplate('list_issues', listIssuesTemplateVariables);\r\n\r\n if ( this.isSpotHaveToBeHighlighted(taskData) ) {\r\n spotsToBeHighlighted.push(taskData);\r\n }\r\n }\r\n }\r\n this.savedIssuesQuantityOnPage = issuesQuantityOnPage;\r\n this.savedIssuesQuantityAll = tasks.length;\r\n spotFixHighlightElements(spotsToBeHighlighted, this);\r\n document.querySelector('.doboard_task_widget-header span').innerHTML += ksesFilter(' ' + getIssuesCounterString(this.savedIssuesQuantityOnPage, this.savedIssuesQuantityAll));\r\n }\r\n\r\n if (tasks.length === 0) {\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML = ksesFilter('The issues list is empty
');\r\n }\r\n\r\n // Bind the click event to the task elements for scrolling to the selected text and Go to concrete issue interface by click issue-item row\r\n this.bindIssuesClick();\r\n hideContainersSpinner(false);\r\n break;\r\n case 'user_menu':\r\n\r\n setToggleStatus(this);\r\n checkLogInOutButtonsVisible();\r\n\r\n const user = await getUserDetails(this.params);\r\n const gitHubAppVersion = await getReleaseVersion();\r\n let spotfixVersion = '';\r\n const version = localStorage.getItem('spotfix_app_version') || gitHubAppVersion || SPOTFIX_VERSION;\r\n spotfixVersion = version ? `Spotfix version ${version}.` : '';\r\n\r\n templateVariables.spotfixVersion = spotfixVersion || '';\r\n\r\n if(user){\r\n templateVariables.userName = user.name || 'Guest';\r\n templateVariables.email = user.email || localStorage.getItem('spotfix_email') || '';\r\n if(user?.avatar?.s) templateVariables.avatar = user?.avatar?.s;\r\n }\r\n\r\n widgetContainer.innerHTML = this.loadTemplate('user_menu', templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n setToggleStatus(this);\r\n checkLogInOutButtonsVisible();\r\n\r\n break;\r\n case 'concrete_issue':\r\n changeSize(container);\r\n tasksFullDetails = await getTasksFullDetails(this.params, this.allTasksData, this.currentActiveTaskId);\r\n const taskDetails = await getTaskFullDetails(tasksFullDetails, this.currentActiveTaskId);\r\n // Update issue title in the interface\r\n const issueTitleElement = document.querySelector('.doboard_task_widget-issue-title');\r\n if (issueTitleElement) {\r\n issueTitleElement.innerText = ksesFilter(taskDetails.issueTitle);\r\n }\r\n\r\n templateVariables.issueTitle = taskDetails?.issueTitle;\r\n templateVariables.issueComments = taskDetails?.issueComments;\r\n\r\n\r\n // Highlight the task's selected text\r\n let nodePath = null;\r\n const currentTaskData = this.allTasksData.find((element) => String(element.taskId) === String(taskDetails.taskId));\r\n let meta = null;\r\n\r\n if (currentTaskData && currentTaskData.taskMeta) {\r\n try {\r\n meta = JSON.parse(currentTaskData.taskMeta);\r\n nodePath = meta.nodePath || null;\r\n } catch (e) { nodePath = null; meta = null; }\r\n }\r\n\r\n templateVariables.taskPageUrl = meta.pageURL;\r\n const taskFormattedPageUrl = meta.pageURL.replace(window.location.origin, '');\r\n templateVariables.taskFormattedPageUrl = taskFormattedPageUrl.length < 2\r\n ? meta.pageURL.replace(window.location.protocol + '/', '') : taskFormattedPageUrl;\r\n templateVariables.contenerClasess = +localStorage.getItem('maximize')\r\n ? 'doboard_task_widget-container-maximize doboard_task_widget-container' : 'doboard_task_widget-container'\r\n widgetContainer.innerHTML = this.loadTemplate('concrete_issue', templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n\r\n // remove old highlights before adding new ones\r\n spotFixRemoveHighlights();\r\n\r\n if (meta && nodePath) {\r\n // Pass the task meta object as an array\r\n spotFixHighlightElements([meta], this);\r\n if (typeof spotFixScrollToNodePath === 'function') {\r\n spotFixScrollToNodePath(nodePath);\r\n }\r\n }\r\n\r\n const issuesCommentsContainer = document.querySelector('.doboard_task_widget-concrete_issues-container');\r\n let dayMessagesData = [];\r\n const initIssuerID = localStorage.getItem('spotfix_user_id');\r\n let userIsIssuer = false;\r\n if ( taskDetails.issueComments.length > 0 ) {\r\n storageRemoveUnreadUpdateForTaskID(taskDetails.taskId);\r\n issuesCommentsContainer.innerHTML = ksesFilter('');\r\n for (const comment of taskDetails.issueComments) {\r\n userIsIssuer = Number(initIssuerID) === Number(comment.commentUserId);\r\n const avatarData = getAvatarData({\r\n taskAuthorAvatarImgSrc: comment.commentAuthorAvatarSrc,\r\n taskAuthorName: comment.commentAuthorName,\r\n });\r\n const commentData = {\r\n commentAuthorName: comment.commentAuthorName,\r\n commentBody: comment.commentBody,\r\n commentDate: comment.commentDate,\r\n commentTime: comment.commentTime,\r\n issueTitle: templateVariables.issueTitle,\r\n avatarCSSClass: avatarData.avatarCSSClass,\r\n avatarStyle: avatarData.avatarStyle,\r\n taskAuthorInitials: avatarData.taskAuthorInitials,\r\n initialsClass: avatarData.initialsClass,\r\n issueMessageClassOwner: userIsIssuer ? 'owner' : 'guest',\r\n };\r\n if (dayMessagesData[comment.commentDate] === undefined) {\r\n dayMessagesData[comment.commentDate] = [];\r\n dayMessagesData[comment.commentDate].push(commentData);\r\n } else {\r\n dayMessagesData[comment.commentDate].push(commentData);\r\n }\r\n }\r\n let daysWrapperHTML = '';\r\n\r\n for (const day in dayMessagesData) {\r\n let currentDayMessages = dayMessagesData[day];\r\n let dayMessagesWrapperHTML = '';\r\n currentDayMessages.sort((a, b) => a.commentTime.localeCompare(b.commentTime));\r\n for (const messageId in currentDayMessages) {\r\n let currentMessageTemplateVariables = currentDayMessages[messageId];\r\n dayMessagesWrapperHTML += this.loadTemplate('concrete_issue_messages', currentMessageTemplateVariables);\r\n }\r\n daysWrapperHTML += this.loadTemplate('concrete_issue_day_content',\r\n {\r\n dayContentMonthDay: day,\r\n dayContentMessages: dayMessagesWrapperHTML,\r\n statusFixedHtml: tasksFullDetails?.taskStatus !== 'DONE' ? '' : this.loadTemplate('fixedTaskHtml')\r\n },\r\n );\r\n }\r\n issuesCommentsContainer.innerHTML = daysWrapperHTML;\r\n } else {\r\n issuesCommentsContainer.innerHTML = ksesFilter('No comments');\r\n }\r\n\r\n // textarea (new comment) behaviour\r\n const textarea = document.querySelector('.doboard_task_widget-send_message_input');\r\n if (textarea) {\r\n function handleTextareaChange() {\r\n const triggerChars = 40;\r\n\r\n if (this.value.length > triggerChars) {\r\n this.classList.add('high');\r\n } else {\r\n this.classList.remove('high');\r\n }\r\n }\r\n textarea.addEventListener('input', handleTextareaChange)\r\n textarea.addEventListener('change', handleTextareaChange)\r\n }\r\n\r\n // Hide spinner preloader\r\n hideContainersSpinner();\r\n\r\n // Scroll to the bottom comments\r\n setTimeout(() => {\r\n const contentContainer = document.querySelector('.doboard_task_widget-content');\r\n contentContainer.scrollTo({\r\n top: contentContainer.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }, 0);\r\n\r\n const sendButton = document.querySelector('.doboard_task_widget-send_message_button');\r\n if (sendButton) {\r\n this.fileUploader.init();\r\n let widgetClass = this;\r\n sendButton.addEventListener('click', async (e) => {\r\n e.preventDefault();\r\n\r\n const sendMessageContainer = sendButton.closest('.doboard_task_widget-send_message');\r\n const input = sendMessageContainer.querySelector('.doboard_task_widget-send_message_input');\r\n\r\n const commentText = input.value.trim();\r\n if (!commentText) return;\r\n\r\n // Add other fields handling here\r\n\r\n input.disabled = true;\r\n sendButton.disabled = true;\r\n\r\n let newCommentResponse = null;\r\n\r\n try {\r\n newCommentResponse = await addTaskComment(this.params, this.currentActiveTaskId, commentText);\r\n input.value = '';\r\n await this.createWidgetElement('concrete_issue');\r\n hideContainersSpinner(false);\r\n } catch (err) {\r\n alert('Error when adding a comment: ' + err.message);\r\n }\r\n\r\n if (widgetClass.fileUploader.hasFiles() && newCommentResponse !== null && newCommentResponse.hasOwnProperty('commentId')) {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n const attachmentsSendResult = await widgetClass.fileUploader.sendAttachmentsForComment(widgetClass.params, sessionId, newCommentResponse.commentId);\r\n if (!attachmentsSendResult.success) {\r\n widgetClass.fileUploader.showError('Some files where no sent, see details in the console.');\r\n const toConsole = JSON.stringify(attachmentsSendResult);\r\n console.log(toConsole);\r\n }\r\n }\r\n\r\n input.disabled = false;\r\n sendButton.disabled = false;\r\n });\r\n }\r\n\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n\r\n const backToAllIssuesController = document.querySelector('.doboard_task_widget_return_to_all');\r\n const widgetClass = this;\r\n if ( backToAllIssuesController ) {\r\n backToAllIssuesController.addEventListener('click', function(e, self = widgetClass) {\r\n self.createWidgetElement('all_issues');\r\n });\r\n }\r\n\r\n const paperclipController = document.querySelector('.doboard_task_widget-send_message_paperclip');\r\n if ( paperclipController ) {\r\n this.fileUploader.bindPaperClipAction(paperclipController);\r\n }\r\n\r\n document.querySelector('.doboard_task_widget-close_btn')?.addEventListener('click', (e) => {\r\n this.hide();\r\n }) || '';\r\n\r\n document.querySelector('#openUserMenuButton')?.addEventListener('click', () => {\r\n this.createWidgetElement('user_menu')\r\n }) || '';\r\n\r\n document.querySelector('#doboard_task_widget-user_menu-logout_button')?.addEventListener('click', () => {\r\n logoutUserDoboard(this.params.projectToken, this.params.accountId).then(() => {this.hide()});\r\n }) || '';\r\n\r\n document.getElementById('addNewTaskButton')?.addEventListener('click', () => {\r\n spotFixShowWidget();\r\n }) || '';\r\n\r\n document.getElementById('maximizeWidgetContainer')?.addEventListener('click', () => {\r\n const container = document.querySelector('.doboard_task_widget-container');\r\n\r\n if(+localStorage.getItem('maximize') && container.classList.contains('doboard_task_widget-container-maximize')){\r\n localStorage.setItem('maximize', '0');\r\n container.classList.remove('doboard_task_widget-container-maximize');\r\n } else {\r\n localStorage.setItem('maximize', '1');\r\n container.classList.add('doboard_task_widget-container-maximize');\r\n }\r\n }) || '';\r\n\r\n document.querySelector('#doboard_task_widget-user_menu-signlog_button')?.addEventListener('click', () => {\r\n spotFixShowWidget();\r\n }) || '';\r\n\r\n document.querySelector('#spotfix_back_button')?.addEventListener('click', () => {\r\n this.createWidgetElement(this.type_name)\r\n }) || '';\r\n\r\n return widgetContainer;\r\n }\r\n\r\n bindIssuesClick() {\r\n document.querySelectorAll('.issue-item').forEach(item => {\r\n item.addEventListener('click', async () => {\r\n let nodePath = null;\r\n try {\r\n nodePath = JSON.parse(item.getAttribute('data-node-path'));\r\n } catch (error) {\r\n nodePath = null;\r\n }\r\n if (nodePath) {\r\n spotFixScrollToNodePath(nodePath);\r\n }\r\n this.currentActiveTaskId = item.getAttribute('data-task-id');\r\n await this.showOneTask();\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Show one task\r\n *\r\n * @return {Promise}\r\n *\r\n */\r\n async showOneTask() {\r\n await this.createWidgetElement('concrete_issue');\r\n const taskHighlightData = this.getTaskHighlightData(this.currentActiveTaskId)\r\n\r\n if (taskHighlightData) {\r\n spotFixRemoveHighlights();\r\n spotFixHighlightElements([taskHighlightData], this)\r\n this.positionWidgetContainer();\r\n }\r\n\r\n hideContainersSpinner(false);\r\n }\r\n\r\n /**\r\n * Load the template\r\n *\r\n * @param templateName\r\n * @param variables\r\n * @return {string}\r\n * @ToDo have to refactor templates loaded method: need to be templates included into the bundle\r\n *\r\n */\r\n loadTemplate(templateName, variables = {}) {\r\n let template = SpotFixTemplatesLoader.getTemplateCode(templateName);\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n const placeholder = `{{${key}}}`;\r\n let replacement;\r\n\r\n // 1) For attributes we MUST use escapeHtml!\r\n // 2) Only for HTML inserts we must clean data by ksesFilter\r\n // Check if placeholder is used in an attribute context\r\n if (this.isPlaceholderInAttribute(template, placeholder)) {\r\n // For attributes, use escapeHtml to prevent XSS\r\n replacement = this.escapeHtml(String(value));\r\n } else {\r\n // For HTML content, use ksesFilter to sanitize HTML\r\n replacement = ksesFilter(String(value), {template: templateName, imgFilter: true});\r\n }\r\n\r\n template = template.replaceAll(placeholder, replacement);\r\n }\r\n\r\n return ksesFilter(template, {template: templateName});\r\n }\r\n\r\n /**\r\n * Check if a placeholder is used inside an HTML attribute\r\n * @param {string} template - The template string\r\n * @param {string} placeholder - The placeholder to check (e.g., \"{{key}}\")\r\n * @return {boolean} - True if placeholder is in an attribute context\r\n */\r\n isPlaceholderInAttribute(template, placeholder) {\r\n // Escape special regex characters in placeholder\r\n const escapedPlaceholder = placeholder.replace(/[{}]/g, '\\\\$&');\r\n\r\n // Pattern to match attribute=\"...\" or attribute='...' containing the placeholder\r\n // This regex looks for: word characters (attribute name) = \" or ' followed by content including the placeholder\r\n // Matches patterns like: src=\"{{key}}\", class=\"{{key}}\", style=\"{{key}}\", etc.\r\n const attributePattern = new RegExp(\r\n `[\\\\w-]+\\\\s*=\\\\s*[\"'][^\"']*${escapedPlaceholder}[^\"']*[\"']`,\r\n 'g'\r\n );\r\n\r\n // Check if placeholder appears in any attribute context\r\n // If it does, we'll use escapeHtml for all occurrences (safer approach)\r\n return attributePattern.test(template);\r\n }\r\n\r\n escapeHtml = (unsafe) => {\r\n return unsafe\r\n .replace(/&/g, \"&\")\r\n .replace(//g, \">\")\r\n .replace(/\"/g, \""\")\r\n .replace(/'/g, \"'\");\r\n };\r\n\r\n async getTaskCount() {\r\n if (!localStorage.getItem('spotfix_session_id')) {\r\n return {};\r\n }\r\n\r\n const projectToken = this.params.projectToken;\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\r\n const tasksCountLS = localStorage.getItem('spotfix_tasks_count');\r\n\r\n let tasksCount;\r\n\r\n if(tasksCountLS !== 0 && !tasksCountLS){\r\n await getTasksDoboard(projectToken, sessionId, this.params.accountId, this.params.projectId);\r\n const tasks = await spotfixIndexedDB.getAll(TABLE_TASKS);\r\n const filteredTasks = tasks.filter(task => {\r\n return task.taskMeta;\r\n });\r\n tasksCount = filteredTasks.length;\r\n } else tasksCount = tasksCountLS;\r\n\r\n const taskCountElement = document.getElementById('doboard_task_widget-task_count');\r\n if ( taskCountElement ) {\r\n taskCountElement.innerText = ksesFilter(tasksCount);\r\n taskCountElement.classList.remove('hidden');\r\n }\r\n }\r\n\r\n /**\r\n * Bind events to the widget\r\n */\r\n /*bindEvents() {\r\n this.submitButton.addEventListener('click', () => this.submitTask());\r\n }*/\r\n\r\n /**\r\n * Submit the task\r\n */\r\n async submitTask(taskDetails) {\r\n if (!localStorage.getItem('spotfix_session_id')) {\r\n await registerUser(taskDetails)(this.registrationShowMessage);\r\n if ( taskDetails.userPassword ) {\r\n await loginUser(taskDetails)(this.registrationShowMessage);\r\n }\r\n }\r\n\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\r\n if ( ! sessionId ) {\r\n // @ToDo move this return in register block code\r\n return {needToLogin: true};\r\n }\r\n return await handleCreateTask(sessionId, taskDetails);\r\n }\r\n\r\n /**\r\n * Hide the widget\r\n */\r\n hide() {\r\n spotFixRemoveHighlights();\r\n this.createWidgetElement('wrap');\r\n\r\n }\r\n\r\n wrapElementWithSpotfixHighlight(element) {\r\n const newElement = element.cloneNode();\r\n const wrapper = document.createElement('span');\r\n wrapper.className = 'doboard_task_widget-text_selection image-highlight';\r\n\r\n element.insertAdjacentElement('beforebegin', wrapper);\r\n wrapper.appendChild(newElement);\r\n\r\n return wrapper;\r\n }\r\n\r\n /**\r\n * Get task spot data for highlighting.\r\n * @param {string|int} taskIdToSearch\r\n * @returns {object|null}\r\n */\r\n getTaskHighlightData(taskIdToSearch) {\r\n const currentTaskData = this.allTasksData.find((element) => element.taskId.toString() === taskIdToSearch.toString());\r\n if (currentTaskData && currentTaskData.taskMeta !== undefined) {\r\n let currentTaskSpotData = null;\r\n try {\r\n currentTaskSpotData = JSON.parse(currentTaskData.taskMeta);\r\n } catch (error) {\r\n currentTaskSpotData = null;\r\n }\r\n if (currentTaskSpotData !== null && typeof currentTaskSpotData === 'object') {\r\n return currentTaskSpotData;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n bindWidgetInputsInteractive() {\r\n // Customising placeholders\r\n const inputs = document.querySelectorAll('.doboard_task_widget-field');\r\n inputs.forEach(input => {\r\n if (input.value) {\r\n input.classList.add('has-value');\r\n }\r\n\r\n input.addEventListener('input', () => {\r\n if (input.value) {\r\n input.classList.add('has-value');\r\n } else {\r\n input.classList.remove('has-value');\r\n }\r\n });\r\n\r\n input.addEventListener('blur', () => {\r\n if (!input.value) {\r\n input.classList.remove('has-value');\r\n }\r\n });\r\n });\r\n\r\n // Customising accordion dropdown\r\n const accordionController = document.querySelector('.doboard_task_widget-login span');\r\n if ( accordionController ) {\r\n const context = this;\r\n accordionController.addEventListener('click', function() {\r\n this.closest('.doboard_task_widget-login').classList.toggle('active');\r\n // Scroll\r\n context.positionWidgetContainer();\r\n setTimeout(() => {\r\n const contentContainer = document.querySelector('.doboard_task_widget-content');\r\n contentContainer.scrollTo({\r\n top: contentContainer.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }, 0);\r\n });\r\n }\r\n\r\n window.addEventListener('scroll', this.handleScroll.bind(this));\r\n window.addEventListener('resize', this.handleResize.bind(this));\r\n }\r\n\r\n registrationShowMessage(messageText, type = 'error') {\r\n const titleSpan = document.getElementById('doboard_task_widget-error_message-header');\r\n const messageDiv = document.getElementById('doboard_task_widget-error_message');\r\n const messageWrap = document.querySelector('.doboard_task_widget-message-wrapper');\r\n\r\n if (typeof messageText === 'string' && messageDiv !== null && messageWrap !== null) {\r\n messageDiv.innerText = ksesFilter(messageText);\r\n messageWrap.classList.remove('hidden');\r\n messageDiv.classList.remove('doboard_task_widget-notice_message', 'doboard_task_widget-error_message');\r\n if (type === 'notice') {\r\n titleSpan.innerText = ksesFilter('');\r\n messageWrap.classList.add('doboard_task_widget-notice_message');\r\n messageDiv.style.color = '#2a5db0';\r\n } else {\r\n titleSpan.innerText = ksesFilter('Registration error');\r\n messageWrap.classList.add('doboard_task_widget-error_message');\r\n messageDiv.style.color = 'red';\r\n }\r\n }\r\n }\r\n\r\n positionWidgetContainer() {\r\n const selection = document.querySelector('.doboard_task_widget-text_selection');\r\n const widget = document.querySelector('.doboard_task_widget')\r\n const widgetCreateIssue = document.querySelector('.doboard_task_widget-content.doboard_task_widget-create_issue')\r\n const widgetConcreteIssue = document.querySelector('.doboard_task_widget-concrete_issues-container')\r\n if ( ! ( ( widgetCreateIssue || widgetConcreteIssue ) && selection ) ) {\r\n // Skip if the widget is closed or highlight not exist\r\n return;\r\n }\r\n\r\n const scrollY = window.scrollY;\r\n const viewportHeight = window.innerHeight;\r\n\r\n const selectionAbsoluteTop = selection.getBoundingClientRect().top + scrollY;\r\n\r\n const widgetHeight = widget.offsetHeight;\r\n\r\n let top;\r\n\r\n // Check selection position\r\n if (selectionAbsoluteTop - scrollY < 0) {\r\n // 1) The selection is above the viewport - stuck the widget on the top\r\n top = 10;\r\n } else if (selectionAbsoluteTop - scrollY > viewportHeight) {\r\n // 2) The selection is below the viewport - stuck the widget on the bottom\r\n top = viewportHeight - widgetHeight - 10;\r\n } else {\r\n // 3) The selection is on viewport - the widget aligned against the selection\r\n top = selectionAbsoluteTop - scrollY\r\n if ( selectionAbsoluteTop - scrollY > viewportHeight - widgetHeight ) {\r\n // 3.1) The selection is on viewport but is below than widget height - stuck the widget on the bottom\r\n top = viewportHeight - widgetHeight - 10;\r\n }\r\n }\r\n\r\n widget.style.top = `${top}px`;\r\n widget.style.bottom = 'auto';\r\n }\r\n\r\n handleScroll() {\r\n clearTimeout(this.scrollTimeout);\r\n this.scrollTimeout = setTimeout(() => {\r\n this.positionWidgetContainer();\r\n }, 10);\r\n }\r\n\r\n handleResize() {\r\n clearTimeout(this.resizeTimeout);\r\n this.resizeTimeout = setTimeout(() => {\r\n this.positionWidgetContainer();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Check nodePath, selectedData against page source and return is the provided nodePath is correct and can be highlighted\r\n * @param taskData\r\n * @return {boolean}\r\n */\r\n isSpotHaveToBeHighlighted(taskData) {\r\n return true;\r\n }\r\n\r\n sanitizeNodePath(nodePath) {\r\n let str = Array.isArray(nodePath) ? JSON.stringify(nodePath) : String(nodePath);\r\n // Allow only digits, commas, spaces, and square brackets\r\n if (/^[\\[\\]0-9,\\s]*$/.test(str)) {\r\n return str;\r\n }\r\n return '';\r\n}\r\n}\r\n\nvar spotFixShowDelayTimeout = null;\r\nconst SPOTFIX_DEBUG = false;\r\nconst SPOTFIX_SHOW_DELAY = 1000;\r\n\r\nif( document.readyState !== 'loading' ) {\r\n document.addEventListener('spotFixLoaded', spotFixInit);\r\n} else {\r\n document.addEventListener('DOMContentLoaded', spotFixInit);\r\n}\r\n\r\nfunction spotFixInit() {\r\n spotfixIndexedDB.init();\r\n wsSpotfix.connect();\r\n wsSpotfix.subscribe();\r\n new SpotFixSourcesLoader();\r\n new CleanTalkWidgetDoboard({}, 'wrap');\r\n loadBotDetector()\r\n}\r\n\r\nfunction loadBotDetector() {\r\nif (document.querySelector('script[src=\"https://moderate.cleantalk.org/ct-bot-detector-wrapper.js\"]') ||\r\n document.getElementById('ct-bot-detector-script')) {\r\n return;\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.src = 'https://moderate.cleantalk.org/ct-bot-detector-wrapper.js';\r\n script.async = true;\r\n script.id = 'ct-bot-detector-script';\r\n document.head.appendChild(script);\r\n}\r\n\r\ndocument.addEventListener('selectionchange', function(e) {\r\n // Do not run widget for non-document events (i.e. inputs focused)\r\n\r\n if (e.target !== document) {\r\n return;\r\n }\r\n\r\n const isWrapReviewWidgetExists = !!(document.getElementsByClassName('wrap_review')[0]);\r\n const sel = document.getSelection();\r\n\r\n if ((!sel || sel.toString() === \"\") && isWrapReviewWidgetExists) {\r\n new CleanTalkWidgetDoboard({}, 'wrap')\r\n return;\r\n }\r\n\r\n if (spotFixShowDelayTimeout) {\r\n clearTimeout(spotFixShowDelayTimeout);\r\n }\r\n\r\n spotFixShowDelayTimeout = setTimeout(() => {\r\n const selection = window.getSelection();\r\n if (\r\n selection.type === 'Range'\r\n ) {\r\n // Check if selection is inside the widget\r\n let anchorNode = selection.anchorNode;\r\n let focusNode = selection.focusNode;\r\n if (spotFixIsInsideWidget(anchorNode) || spotFixIsInsideWidget(focusNode)) {\r\n return;\r\n }\r\n const selectedData = spotFixGetSelectedData(selection);\r\n\r\n if ( selectedData ) {\r\n // spotFixOpenWidget(selectedData, 'create_issue');\r\n spotFixOpenWidget(selectedData, 'wrap_review');\r\n }\r\n }\r\n }, SPOTFIX_SHOW_DELAY);\r\n});\r\n\r\n\r\n/**\r\n * Shows the spot fix widget.\r\n */\r\nfunction spotFixShowWidget() {\r\n new CleanTalkWidgetDoboard(null, 'create_issue');\r\n}\r\n\r\n/**\r\n * Check if a node is inside the task widget.\r\n * @param {*} node\r\n * @returns {boolean}\r\n */\r\nfunction spotFixIsInsideWidget(node) {\r\n if (!node) return false;\r\n let el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\r\n while (el) {\r\n if (el.classList && el.classList.contains('doboard_task_widget')) {\r\n return true;\r\n }\r\n el = el.parentElement;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Open the widget to create a task.\r\n * @param {*} selectedData\r\n * @param {*} type\r\n */\r\nfunction spotFixOpenWidget(selectedData, type) {\r\n if (selectedData) {\r\n new CleanTalkWidgetDoboard(selectedData, type);\r\n }\r\n}\r\n\r\n/**\r\n * Write message into the console.\r\n *\r\n * @param {string} message\r\n */\r\nfunction spotFixDebugLog(message) {\r\n if ( SPOTFIX_DEBUG ) {\r\n console.log(message);\r\n }\r\n}\r\n\r\nfunction hideContainersSpinner() {\r\n const spinners = document.getElementsByClassName('doboard_task_widget-spinner_wrapper_for_containers');\r\n if (spinners.length > 0) {\r\n for (let i = 0; i < spinners.length ; i++) {\r\n spinners[i].style.display = 'none';\r\n }\r\n }\r\n const containerClassesToShow = ['doboard_task_widget-all_issues-container', 'doboard_task_widget-concrete_issues-container'];\r\n for (let i = 0; i < containerClassesToShow.length ; i++) {\r\n const containers = document.getElementsByClassName(containerClassesToShow[i]);\r\n if (containers.length > 0) {\r\n for (let i = 0; i < containers.length ; i++) {\r\n containers[i].style.display = 'block';\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction getTaskFullDetails(tasksDetails, taskId) {\r\n const comments = tasksDetails.comments.filter(comment => {\r\n return comment?.taskId?.toString() === taskId?.toString()\r\n });\r\n const users = tasksDetails.users;\r\n // Last comment\r\n let lastComment = comments.length > 0 ? comments[0] : null;\r\n // Author of the last comment\r\n let author = null;\r\n if (lastComment && users && users.length > 0) {\r\n author = users.find(u => String(u.user_id) === String(lastComment.userId));\r\n }\r\n // Format date\r\n let date = '', time = '';\r\n if (lastComment) {\r\n const dt = formatDate(lastComment.commentDate);\r\n date = dt.date;\r\n time = dt.time;\r\n }\r\n // Get the avatar and the name through separate functions\r\n let avatarSrc = getAvatarSrc(author);\r\n let authorName = getAuthorName(author);\r\n\r\n return {\r\n taskId: taskId,\r\n taskAuthorAvatarImgSrc: avatarSrc,\r\n taskAuthorName: authorName,\r\n lastMessageText: lastComment ? lastComment.commentBody : 'No messages yet',\r\n lastMessageTime: time,\r\n issueTitle: comments.length > 0 ? comments[0].issueTitle : 'No Title',\r\n issueComments: comments\r\n .sort((a, b) => {\r\n return new Date(a.commentDate) - new Date(b.commentDate);\r\n })\r\n .map(comment => {\r\n const {date, time} = formatDate(comment.commentDate);\r\n let author = null;\r\n if (users && users.length > 0) {\r\n author = users.find(u => String(u.user_id) === String(comment.userId));\r\n }\r\n return {\r\n commentAuthorAvatarSrc: getAvatarSrc(author),\r\n commentAuthorName: getAuthorName(author),\r\n commentBody: comment.commentBody,\r\n commentDate: date,\r\n commentTime: time,\r\n commentUserId: comment.userId || 'Unknown User',\r\n };\r\n })\r\n };\r\n}\r\n\r\nfunction getAvatarData(authorDetails) {\r\n let avatarStyle;\r\n let avatarCSSClass;\r\n let taskAuthorInitials =\r\n authorDetails.taskAuthorName && authorDetails.taskAuthorName != 'Anonymous'\r\n ? authorDetails.taskAuthorName.trim().charAt(0).toUpperCase()\r\n : null;\r\n let initialsClass = 'doboard_task_widget-avatar-initials';\r\n if (authorDetails.taskAuthorAvatarImgSrc === null && taskAuthorInitials !== null) {\r\n avatarStyle = 'display: flex;background-color: #f8de7e;justify-content: center;align-items: center;';\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n }\r\n if (authorDetails.taskAuthorAvatarImgSrc === null && taskAuthorInitials === null) {\r\n avatarStyle = `background-image:url(\\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAE9GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4wLWMwMDAgNzkuMTcxYzI3ZmFiLCAyMDIyLzA4LzE2LTIyOjM1OjQxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjQuMCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjQtMDQtMTBUMTk6MDg6MDkrMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxNWRjOWI0Yy04ZWVmLTRkNTEtYmE0MS1kOTkzZTZmNjNmMTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTVkYzliNGMt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');`;\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n initialsClass += ' doboard_task_widget-hidden_element';\r\n }\r\n if (authorDetails.taskAuthorAvatarImgSrc !== null) {\r\n avatarStyle = `background-image:url(\\'${authorDetails.taskAuthorAvatarImgSrc}\\');`;\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n initialsClass = 'doboard_task_widget-hidden_element';\r\n }\r\n return {\r\n avatarStyle: avatarStyle,\r\n avatarCSSClass: avatarCSSClass,\r\n taskAuthorInitials: taskAuthorInitials,\r\n initialsClass: initialsClass\r\n }\r\n}\r\n\r\n/**\r\n * Return first found updated task ID or false if no tasks were updated\r\n * @param allTasksData\r\n * @returns {string[]|false}\r\n */\r\nfunction isAnyTaskUpdated(allTasksData) {\r\n let result = false;\r\n\r\n const updatedtasksIDS = [];\r\n\r\n for (let i = 0; i < allTasksData.length; i++) {\r\n const currentStateOfTask = allTasksData[i];\r\n const issuerId = localStorage.getItem('spotfix_user_id');\r\n if (\r\n currentStateOfTask.taskId &&\r\n currentStateOfTask.taskLastUpdate &&\r\n currentStateOfTask.taskCreatorTaskUser.toString() === issuerId.toString()\r\n ) {\r\n result = storageCheckTaskUpdate(currentStateOfTask.taskId, currentStateOfTask.taskLastUpdate);\r\n if (result) {\r\n updatedtasksIDS.push(currentStateOfTask.taskId.toString());\r\n }\r\n }\r\n }\r\n\r\n return updatedtasksIDS.length === 0 ? false : updatedtasksIDS;\r\n}\r\n\r\n/**\r\n * Check if any of the tasks has updates from site owner (not from the current user and not anonymous)\r\n * @returns {Promise}\r\n */\r\nasync function checkIfTasksHasSiteOwnerUpdates(allTasksData, params) {\r\n const updatedTaskIDs = isAnyTaskUpdated(allTasksData);\r\n let result = false;\r\n if (!updatedTaskIDs) {\r\n return false;\r\n }\r\n for (let i = 0; i < updatedTaskIDs.length; i++) {\r\n const updatedTaskId = updatedTaskIDs[i];\r\n if (typeof updatedTaskId === 'string') {\r\n const updatedTaskData = await getTasksFullDetails(params, [updatedTaskId]);\r\n if (updatedTaskData.comments) {\r\n const lastMessage = updatedTaskData.comments[0];\r\n if (\r\n lastMessage.commentUserId !== undefined &&\r\n lastMessage.commentUserId !== localStorage.getItem('spotfix_user_id') &&\r\n lastMessage.commentAuthorName !== 'Anonymous'\r\n ) {\r\n storageAddUnreadUpdateForTaskID(updatedTaskId);\r\n result = true;\r\n }\r\n }\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if the selection is correct - do not allow to select all page, or several different nesting nodes, or something else\r\n * @param selection\r\n * @return {boolean}\r\n */\r\nfunction isSelectionCorrect(selection) {\r\n return true;\r\n}\r\n\r\n/**\r\n * Sanitize HTML\r\n * @param {*} html\r\n * @param {*} options\r\n * @returns\r\n */\r\nfunction ksesFilter(html, options = false) {\r\n let allowedTags = {\r\n a: true,\r\n b: true,\r\n i: true,\r\n strong: true,\r\n em: true,\r\n ul: true,\r\n ol: true,\r\n li: true,\r\n p: true,\r\n s: true,\r\n br: true,\r\n span: true,\r\n blockquote: true,\r\n pre: true,\r\n div: true,\r\n img: true,\r\n input: true,\r\n label: true,\r\n textarea: true,\r\n button: true,\r\n blockquote: true,\r\n pre: true,\r\n details: true,\r\n summary: true,\r\n };\r\n let allowedAttrs = {\r\n a: ['href', 'title', 'target', 'rel', 'style', 'class'],\r\n span: ['style', 'class', 'id'],\r\n p: ['style', 'class'],\r\n div: ['style', 'class', 'id', 'data-node-path', 'data-task-id'],\r\n img: ['src', 'alt', 'title', 'class', 'style', 'width', 'height'],\r\n input: ['type', 'class', 'style', 'id', 'multiple', 'accept', 'value'],\r\n label: ['for', 'class', 'style'],\r\n textarea: ['class', 'id', 'style', 'rows', 'cols', 'readonly', 'required', 'name'],\r\n button: ['type', 'class', 'style', 'id'],\r\n details: ['class', 'style', 'open'],\r\n summary: ['class', 'style'],\r\n };\r\n\r\n if (options && options.template === 'list_issues') {\r\n allowedTags = { ...allowedTags, br: false };\r\n }\r\n\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(html, 'text/html');\r\n function clean(node) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const tag = node.tagName.toLowerCase();\r\n\r\n if (options) {\r\n if (allowedTags[tag]) {\r\n // Special handling for images in 'concrete_issue_day_content' template (wrap img in link always)\r\n if (tag === 'img' && options.template === 'concrete_issue_day_content' && options.imgFilter) {\r\n const src = node.getAttribute('src') || '';\r\n const alt = node.getAttribute('alt') || '[image]';\r\n const link = doc.createElement('a');\r\n link.href = src;\r\n link.target = '_blank';\r\n link.className = 'doboard_task_widget-img-link';\r\n const img = doc.createElement('img');\r\n img.src = src;\r\n img.alt = alt;\r\n img.className = 'doboard_task_widget-comment_body-img-strict';\r\n link.appendChild(img);\r\n node.parentNode.insertBefore(link, node);\r\n node.remove();\r\n return;\r\n }\r\n }\r\n\r\n if (!allowedTags[tag]) {\r\n // Special handling for images in 'list_issues' template\r\n if (tag === 'img' && options.template === 'list_issues' && options.imgFilter) {\r\n const src = node.getAttribute('src') || '';\r\n const alt = node.getAttribute('alt') || '[image]';\r\n const link = doc.createElement('a');\r\n link.href = src;\r\n link.target = '_blank';\r\n link.textContent = alt;\r\n node.parentNode.insertBefore(link, node);\r\n }\r\n node.remove();\r\n return;\r\n }\r\n }\r\n\r\n // Remove disallowed attributes\r\n [...node.attributes].forEach(attr => {\r\n const attrName = attr.name.toLowerCase();\r\n if (!allowedAttrs[tag]?.includes(attrName) ||\r\n attrName.startsWith('on') || // Remove event handlers\r\n attr.value.toLowerCase().includes('javascript:')) {\r\n node.removeAttribute(attr.name);\r\n }\r\n });\r\n }\r\n // Recursively clean children\r\n [...node.childNodes].forEach(clean);\r\n }\r\n [...doc.body.childNodes].forEach(clean);\r\n return doc.body.innerHTML;\r\n}\r\n\n/**\r\n * SELECTION will be grouped into three types:\r\n * 1 - Simple text within a single tag\r\n * 2 - Image tags\r\n * 3 - Any tag containing nested content\r\n * Each type will be processed differently.\r\n */\r\nconst SPOTFIX_SELECTION_TYPE_TEXT = 'text';\r\nconst SPOTFIX_SELECTION_TYPE_IMG = 'image';\r\nconst SPOTFIX_SELECTION_TYPE_ELEMENT = 'element';\r\n\r\n/**\r\n * Determines the type of selection\r\n * @param {Selection} selection - The DOM Selection object\r\n * @returns {string|null} Selection type\r\n */\r\nfunction spotFixGetSelectionType(selection) {\r\n const range = selection.getRangeAt(0);\r\n const commonAncestor = range.commonAncestorContainer;\r\n\r\n // Case 1: Image selection\r\n if (spotFixGetSelectedImage(selection)) {\r\n return SPOTFIX_SELECTION_TYPE_IMG;\r\n }\r\n\r\n // Case 2: Element with nested content\r\n if (commonAncestor.nodeType === Node.ELEMENT_NODE &&\r\n commonAncestor.childNodes.length > 1 &&\r\n range.toString().trim() === '' &&\r\n range.startContainer === range.endContainer &&\r\n range.startContainer.nodeType === Node.ELEMENT_NODE) {\r\n return SPOTFIX_SELECTION_TYPE_ELEMENT;\r\n }\r\n\r\n // Case 3: Simple text\r\n const hasTextContent = range.toString().trim().length > 0;\r\n const isTextNode = commonAncestor.nodeType === Node.TEXT_NODE;\r\n const isCollapsed = range.collapsed;\r\n\r\n if (hasTextContent && (isTextNode || !isCollapsed)) {\r\n return SPOTFIX_SELECTION_TYPE_TEXT;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extracts selection data from DOM Selection object\r\n * @param {Selection} selection - The DOM Selection object\r\n * @returns {Object|null} Selection data with text, positions, URL and node path OR null (nothing)\r\n */\r\nfunction spotFixGetSelectedData(selection) {\r\n // Prechecks:\r\n // Selection not provided\r\n if (!selection) {spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection not provided`'); return null; }\r\n // Range not provided\r\n if (selection.rangeCount === 0) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Range not provided`'); return null; }\r\n // Several ranges provided\r\n if (selection.rangeCount > 1) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Several ranges provided`'); return null; }\r\n\r\n const range = selection.getRangeAt(0);\r\n // Selection must be within a single DOM element.\r\n if (range.startContainer !== range.endContainer) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection within several tags nodes`'); return null; }\r\n\r\n // FIRST - check selection type\r\n const selectionType = spotFixGetSelectionType(selection);\r\n\r\n // Selection type not determined\r\n if (!selectionType) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection type not determined`'); return null; }\r\n\r\n // SECOND - generate selectedData for each selectionType\r\n let selectedText = '';\r\n let startSelectPosition = 0;\r\n let endSelectPosition = 0;\r\n let nodePath = '';\r\n let imageUrl = '';\r\n\r\n const commonNode = range.commonAncestorContainer;\r\n\r\n switch (selectionType) {\r\n case SPOTFIX_SELECTION_TYPE_TEXT:\r\n if (range.toString().trim().length === 0) {\r\n spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection text is empty`');\r\n return null;\r\n }\r\n const commonNodeElement = commonNode.nodeType === Node.ELEMENT_NODE ? commonNode : commonNode.parentElement;\r\n selectedText = range.toString();\r\n startSelectPosition = range.startOffset;\r\n endSelectPosition = range.endOffset;\r\n if ( startSelectPosition === 0 && selectedText.length > endSelectPosition ) {\r\n endSelectPosition = selectedText.length;\r\n }\r\n nodePath = spotFixCalculateNodePath(commonNodeElement);\r\n break;\r\n\r\n case SPOTFIX_SELECTION_TYPE_IMG:\r\n const imgElement = range.startContainer;\r\n const selectedImage = spotFixGetSelectedImage(selection);\r\n selectedText = `Image (${selectedImage.alt ? selectedImage.alt : 'no description'})`;\r\n nodePath = spotFixCalculateNodePath(selectedImage);\r\n // For images, positions represent the image element position in parent\r\n startSelectPosition = Array.from(imgElement.parentNode.children).indexOf(imgElement);\r\n endSelectPosition = startSelectPosition + 1;\r\n break;\r\n\r\n case SPOTFIX_SELECTION_TYPE_ELEMENT:\r\n const element = commonNode.nodeType === Node.ELEMENT_NODE ? commonNode : commonNode.parentElement;\r\n if (element.childNodes.length <= 1) {\r\n spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection have not inner data`');\r\n return null;\r\n }\r\n selectedText = element.textContent || '';\r\n nodePath = spotFixCalculateNodePath(element);\r\n // For elements, positions represent the element's position in parent\r\n startSelectPosition = Array.from(element.parentNode.children).indexOf(element);\r\n endSelectPosition = startSelectPosition + 1;\r\n break;\r\n }\r\n\r\n // Get page URL\r\n const pageURL = window.location.href;\r\n\r\n return {\r\n startSelectPosition,\r\n endSelectPosition,\r\n selectedText: selectedText.trim(),\r\n pageURL,\r\n nodePath,\r\n selectionType,\r\n imageUrl: selectionType === SPOTFIX_SELECTION_TYPE_IMG ? imageUrl : ''\r\n };\r\n}\r\n\r\n/**\r\n * Highlight elements.\r\n * @param {[object]} spotsToBeHighlighted\r\n * @param widgetInstance\r\n */\r\nfunction spotFixHighlightElements(spotsToBeHighlighted, widgetInstance) {\r\n\r\n if (spotsToBeHighlighted.length === 0) return;\r\n\r\n const elementsMap = new Map();\r\n\r\n // Grouping elements with validation\r\n spotsToBeHighlighted.forEach(spot => {\r\n // nodePath validating: is array\r\n if (!spot?.nodePath || !Array.isArray(spot?.nodePath)) {\r\n spotFixDebugLog('Invalid spot: missing or invalid nodePath: ' + spot);\r\n return;\r\n }\r\n\r\n // nodePath validating: is valid indexes list\r\n if (!this.spotFixIsValidNodePath(spot.nodePath)) {\r\n spotFixDebugLog('Invalid nodePath format: ' + spot.nodePath);\r\n return;\r\n }\r\n\r\n const element = spotFixRetrieveNodeFromPath(spot.nodePath);\r\n if (!element) {\r\n spotFixDebugLog('Element not found for path: ' + spot.nodePath);\r\n return;\r\n }\r\n\r\n if ( ! spot.selectionType ) {\r\n // @ToDo need to apply backward capability here\r\n // just `spot.selectionType = 'text';` is not able, this opens ability to unauthorized modify website content\r\n spotFixDebugLog('Selection type is not provided.');\r\n return;\r\n }\r\n\r\n // selectionType parameter validating\r\n if (\r\n spot.selectionType &&\r\n ![\r\n SPOTFIX_SELECTION_TYPE_TEXT,\r\n SPOTFIX_SELECTION_TYPE_IMG,\r\n SPOTFIX_SELECTION_TYPE_ELEMENT\r\n ].includes(spot.selectionType)\r\n ) {\r\n spotFixDebugLog('Invalid selection type: ' + spot.selectionType);\r\n return;\r\n }\r\n\r\n if (!elementsMap.has(element)) {\r\n elementsMap.set(element, []);\r\n }\r\n elementsMap.get(element).push(spot);\r\n });\r\n\r\n elementsMap.forEach((spots, element) => {\r\n const selectionType = spots[0].selectionType;\r\n\r\n // MAIN LOGIC: highlight for the different types\r\n switch (selectionType) {\r\n case 'image':\r\n this.spotFixHighlightImageElement(element);\r\n break;\r\n\r\n case 'element':\r\n this.spotFixHighlightNestedElement(element);\r\n break;\r\n\r\n case 'text':\r\n this.spotFixHighlightTextInElement(element, spots, widgetInstance);\r\n break;\r\n\r\n default:\r\n spotFixDebugLog('Unknown selection type: ' + selectionType);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Highlight image element by adding class\r\n * @param {Element} element\r\n */\r\nfunction spotFixHighlightImageElement(element) {\r\n if (element.tagName !== 'IMG') {\r\n spotFixDebugLog('Expected IMG element for image highlight, got: ' + element.tagName);\r\n return;\r\n }\r\n element.classList.add('doboard_task_widget-image_selection');\r\n}\r\n\r\n/**\r\n * Highlight nested element by adding class\r\n * @param {Element} element\r\n */\r\nfunction spotFixHighlightNestedElement(element) {\r\n element.classList.add('doboard_task_widget-element_selection');\r\n}\r\n\r\n/**\r\n * Highlight text in element with span wrapping\r\n * @param {Element} element\r\n * @param {Array} spots\r\n * @param widgetInstance\r\n */\r\nfunction spotFixHighlightTextInElement(element, spots,widgetInstance) {\r\n let tooltipTitleText = '';\r\n if (spots[0].isFixed) {\r\n tooltipTitleText = `This issue already fixed.`;\r\n } else {\r\n tooltipTitleText = `We are already working on this issue.`;\r\n }\r\n\r\n const tooltip = `\r\n
\r\n
\r\n ${tooltipTitleText}
\r\n You can see history Here
\r\n \r\n
`;\r\n\r\n const spotfixHighlightOpen = `${tooltip} `;\r\n const spotfixHighlightClose = ` `;\r\n\r\n let text = element.textContent;\r\n const spotSelectedText = spots[0].selectedText;\r\n\r\n // meta.selectedText can not be empty string\r\n if ( ! spotSelectedText ) {\r\n spotFixDebugLog('Provided metadata is invalid.');\r\n return;\r\n }\r\n\r\n const markers = [];\r\n\r\n // Mark positions for inserting\r\n spots.forEach(spot => {\r\n // Validating positions\r\n const startPos = parseInt(spot.startSelectPosition) || 0;\r\n const endPos = parseInt(spot.endSelectPosition) || 0;\r\n\r\n if (startPos < 0 || endPos > text.length || startPos > endPos) {\r\n spotFixDebugLog('Invalid text positions: ' + spot);\r\n return;\r\n }\r\n\r\n markers.push({ position: startPos, type: 'start' });\r\n markers.push({ position: endPos, type: 'end' });\r\n });\r\n\r\n if (markers.length === 0) return;\r\n\r\n // Sort markers backward\r\n markers.sort((a, b) => b.position - a.position);\r\n\r\n // Check here that element (from meta.nodePath) contains same inner text as in meta.selectedText\r\n // Is the `text` in the element equal to the selected text `spotSelectedText`\r\n if ( text.slice(markers[1].position, markers[0].position) !== spotSelectedText ) {\r\n spotFixDebugLog('It is not allow to highlight element by provided metadata.');\r\n return;\r\n }\r\n\r\n let result = text;\r\n markers.forEach(marker => {\r\n const insertText = marker.type === 'start'\r\n ? spotfixHighlightOpen\r\n : spotfixHighlightClose;\r\n\r\n result = result.slice(0, marker.position) + insertText + result.slice(marker.position);\r\n });\r\n\r\n // Safety HTML insert\r\n try {\r\n element.innerHTML = ksesFilter(result);\r\n document.querySelectorAll('.doboard_task_widget-see-task').forEach(link => {\r\n link.addEventListener('click', (e) => {\r\n\r\n e.preventDefault();\r\n const classList = link.className.split(' ');\r\n const idClass = classList.find(cls => cls.includes('__task-id-'));\r\n let taskId = null;\r\n if (idClass) {\r\n taskId = idClass.split('__task-id-')[1];\r\n }\r\n if (taskId) {\r\n widgetInstance.currentActiveTaskId = taskId;\r\n widgetInstance.showOneTask();\r\n }\r\n });\r\n });\r\n } catch (error) {\r\n spotFixDebugLog('Error updating element content: ' + error);\r\n }\r\n}\r\n\r\n/**\r\n * Scroll to an element by tag, class, and text content\r\n * @param {array} path - The path to the element\r\n * @return {boolean} - True if the element was found and scrolled to, false otherwise\r\n */\r\nfunction spotFixScrollToNodePath(path) {\r\n const node = spotFixRetrieveNodeFromPath(path);\r\n if (node && node.scrollIntoView) {\r\n node.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\nfunction spotFixRemoveHighlights() {\r\n const textSelectionclassName = 'doboard_task_widget-text_selection';\r\n const spans = document.querySelectorAll('.' + textSelectionclassName);\r\n const affectedParents = new Set(); // Track unique parents\r\n\r\n spans.forEach(span => {\r\n const parent = span.parentNode;\r\n affectedParents.add(parent); // Mark parent as affected\r\n const tooltip = span.querySelector('.doboard_task_widget-text_selection_tooltip');\r\n if (tooltip) tooltip.remove();\r\n\r\n // Move all child nodes out of the span and into the parent\r\n while (span.firstChild) {\r\n parent.insertBefore(span.firstChild, span);\r\n }\r\n parent.removeChild(span);\r\n });\r\n\r\n // Normalize all affected parents to merge adjacent text nodes\r\n affectedParents.forEach(parent => parent.normalize());\r\n\r\n const elementSelectionClassName = 'doboard_task_widget-element_selection';\r\n const elements = document.querySelectorAll(`.${elementSelectionClassName}`);\r\n elements.forEach(element => {\r\n element.classList.remove(elementSelectionClassName);\r\n });\r\n const imageSelectionClassName = 'doboard_task_widget-image_selection';\r\n const images = document.querySelectorAll(`.${imageSelectionClassName}`);\r\n images.forEach(element => {\r\n element.classList.remove(imageSelectionClassName);\r\n });\r\n}\r\n\r\n/**\r\n * Validate nodePath as array of indices\r\n * @param {Array} nodePath\r\n * @returns {boolean}\r\n */\r\nfunction spotFixIsValidNodePath(nodePath) {\r\n if (!Array.isArray(nodePath)) return false;\r\n if (nodePath.length === 0) return false;\r\n\r\n return nodePath.every(index => {\r\n return Number.isInteger(index) && index >= 0 && index < 1000;\r\n });\r\n}\r\n\r\n/**\r\n * Try to find selected image in selection.\r\n * @param selection\r\n * @returns {Node|*|null}\r\n */\r\nfunction spotFixGetSelectedImage(selection) {\r\n\r\n if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {\r\n return null;\r\n }\r\n\r\n const range = selection.getRangeAt(0);\r\n\r\n // Is current end container IMG\r\n if (range.startContainer === range.endContainer &&\r\n range.startContainer.nodeType === Node.ELEMENT_NODE &&\r\n range.startContainer.tagName === 'IMG') {\r\n return range.startContainer;\r\n }\r\n\r\n // Get img in the range\r\n const walker = document.createTreeWalker(\r\n range.commonAncestorContainer,\r\n NodeFilter.SHOW_ELEMENT,\r\n {\r\n acceptNode: function(node) {\r\n return node.tagName === 'IMG' &&\r\n spotFixIsElementInRange(node, range) ?\r\n NodeFilter.FILTER_ACCEPT :\r\n NodeFilter.FILTER_REJECT;\r\n }\r\n }\r\n );\r\n\r\n let imgNode = walker.nextNode();\r\n if (imgNode) {\r\n return imgNode;\r\n }\r\n\r\n // start/end containers\r\n const startElement = spotFixGetElementFromNode(range.startContainer);\r\n const endElement = spotFixGetElementFromNode(range.endContainer);\r\n\r\n // If selection starts on image\r\n if (startElement && startElement.tagName === 'IMG' &&\r\n spotFixIsElementPartiallySelected(startElement, range)) {\r\n return startElement;\r\n }\r\n\r\n if (endElement && endElement.tagName === 'IMG' &&\r\n spotFixIsElementPartiallySelected(endElement, range)) {\r\n return endElement;\r\n }\r\n\r\n // 4. Get closest IMG\r\n const nearbyElements = spotFixFindNearbyElements(range);\r\n for (const element of nearbyElements) {\r\n if (element.tagName === 'IMG') {\r\n return element;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction spotFixIsElementInRange(element, range) {\r\n const elementRange = document.createRange();\r\n elementRange.selectNode(element);\r\n return range.compareBoundaryPoints(Range.START_TO_START, elementRange) <= 0 &&\r\n range.compareBoundaryPoints(Range.END_TO_END, elementRange) >= 0;\r\n}\r\n\r\nfunction spotFixIsElementPartiallySelected(element, range) {\r\n const elementRect = element.getBoundingClientRect();\r\n const rangeRect = range.getBoundingClientRect();\r\n\r\n // bounding rectangles is crossed\r\n return !(elementRect.right < rangeRect.left ||\r\n elementRect.left > rangeRect.right ||\r\n elementRect.bottom < rangeRect.top ||\r\n elementRect.top > rangeRect.bottom);\r\n}\r\n\r\nfunction spotFixGetElementFromNode(node) {\r\n return node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\r\n}\r\n\r\n/**\r\n * Find nearby elements in the range.\r\n * @param range\r\n * @returns {*[]}\r\n */\r\nfunction spotFixFindNearbyElements(range) {\r\n const elements = [];\r\n const container = range.commonAncestorContainer;\r\n\r\n // search elements\r\n const previousElement = container.previousElementSibling;\r\n const nextElement = container.nextElementSibling;\r\n\r\n if (previousElement) {\r\n elements.push(previousElement);\r\n }\r\n if (nextElement) {\r\n elements.push(nextElement);\r\n }\r\n\r\n // Also check child container\r\n if (container.nodeType === Node.ELEMENT_NODE) {\r\n const children = container.children;\r\n for (let i = 0; i < children.length; i++) {\r\n if (spotFixIsElementPartiallySelected(children[i], range)) {\r\n elements.push(children[i]);\r\n }\r\n }\r\n }\r\n\r\n return elements;\r\n}\r\n\r\n/**\r\n * Calculate the path of a DOM node\r\n *\r\n * @param {Node} node\r\n * @return {int[]}\r\n */\r\nfunction spotFixCalculateNodePath(node) {\r\n let path = [];\r\n while (node) {\r\n let index = 0;\r\n let sibling = node.previousSibling;\r\n while (sibling) {\r\n if (sibling.nodeType === 1) {\r\n index++;\r\n }\r\n sibling = sibling.previousSibling;\r\n }\r\n path.unshift(index);\r\n node = node.parentNode;\r\n }\r\n\r\n // Hard fix - need to remove first element to work correctly\r\n path.shift();\r\n\r\n return path;\r\n}\r\n\r\n/**\r\n * Retrieve a DOM node from a path\r\n *\r\n * @param {int[]} path\r\n * @return {*|null}\r\n */\r\nfunction spotFixRetrieveNodeFromPath(path) {\r\n // @ToDo check if the path is correct\r\n if ( ! path ) {\r\n return null;\r\n }\r\n\r\n let node = document;\r\n for (let i = 0; i < path.length; i++) {\r\n node = node.children[path[i]];\r\n if ( ! node ) {\r\n return null;\r\n }\r\n }\r\n return node;\r\n}\r\n\n/**\r\n * Return bool if widget is closed in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageGetWidgetIsClosed() {\r\n return localStorage.getItem('spotfix_widget_is_closed') === '1';\r\n}\r\n\r\n/**\r\n * Return bool if widget closed state is defined in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageWidgetCloseIsSet() {\r\n return localStorage.getItem('spotfix_widget_is_closed') !== null;\r\n}\r\n\r\n/**\r\n * Save widget closed state\r\n * @param visible\r\n */\r\nfunction storageSetWidgetIsClosed(visible) {\r\n localStorage.setItem('spotfix_widget_is_closed', visible ? '1' : '0');\r\n if(visible) {\r\n wsSpotfix.close();\r\n } else {\r\n wsSpotfix.connect();\r\n wsSpotfix.subscribe();\r\n }\r\n}\r\n\r\n/**\r\n * Return bool if user is defined in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageGetUserIsDefined() {\r\n return localStorage.getItem('spotfix_user_id') !== null;\r\n}\r\n\r\n/**\r\n * Save data for updates check\r\n * @param tasks\r\n */\r\nfunction storageSaveTasksUpdateData(tasks) {\r\n if (!tasks || !Array.isArray(tasks)) {\r\n return;\r\n }\r\n\r\n let storedTasks = {};\r\n try {\r\n storedTasks = JSON.parse(localStorage.getItem('spotfix_task_updates') || '{}');\r\n } catch (error) {\r\n storedTasks = {};\r\n }\r\n\r\n tasks.forEach(task => {\r\n if (task.taskId && task.taskLastUpdate) {\r\n storedTasks[task.taskId] = {\r\n taskId: task.taskId,\r\n taskLastUpdate: task.taskLastUpdate\r\n };\r\n }\r\n });\r\n\r\n localStorage.setItem('spotfix_task_updates', JSON.stringify(storedTasks));\r\n}\r\n\r\nfunction storageSaveTasksCount(tasks) {\r\n if (!tasks || !Array.isArray(tasks)) {\r\n return;\r\n }\r\n\r\n const count = tasks.filter(task => {\r\n return task.taskMeta;\r\n })?.length;\r\n\r\n localStorage.setItem('spotfix_tasks_count', `${count}`);\r\n}\r\n\r\n/**\r\n * Check if a specific task has been updated since last check\r\n * @param taskId\r\n * @param currentLastUpdate\r\n * @returns {boolean|null}\r\n */\r\nfunction storageCheckTaskUpdate(taskId, currentLastUpdate) {\r\n if (!taskId || !currentLastUpdate) {\r\n return null;\r\n }\r\n\r\n let storedTasks = {};\r\n try {\r\n storedTasks = JSON.parse(localStorage.getItem('spotfix_task_updates') || '{}');\r\n } catch (error) {\r\n storedTasks = {};\r\n }\r\n const storedTask = storedTasks[taskId];\r\n\r\n if (!storedTask) {\r\n return false;\r\n }\r\n\r\n const storedUpdate = new Date(storedTask.taskLastUpdate);\r\n const currentUpdate = new Date(currentLastUpdate);\r\n return currentUpdate > storedUpdate;\r\n}\r\n\r\n/**\r\n * Add unread update for a specific task\r\n * @param taskId\r\n */\r\nfunction storageAddUnreadUpdateForTaskID(taskId) {\r\n if (!taskId) {\r\n return;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n if (!storedUnread.includes(taskId)) {\r\n storedUnread.push(taskId);\r\n }\r\n\r\n localStorage.setItem('spotfix_unread_updates', JSON.stringify(storedUnread));\r\n}\r\n\r\n/**\r\n * Remove unread update for a specific task\r\n * @param taskId\r\n */\r\nfunction storageRemoveUnreadUpdateForTaskID(taskId) {\r\n if (!taskId) {\r\n return;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n storedUnread = storedUnread.filter(id => id !== taskId);\r\n localStorage.setItem('spotfix_unread_updates', JSON.stringify(storedUnread));\r\n}\r\n\r\n/**\r\n * Check if there are any unread updates\r\n * @returns {boolean}\r\n */\r\nfunction storageTasksHasUnreadUpdates() {\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n return storedUnread.length > 0;\r\n}\r\n\r\n/**\r\n * Check if a specific task has unread updates\r\n * @param taskId\r\n * @returns {boolean}\r\n */\r\nfunction storageProvidedTaskHasUnreadUpdates(taskId) {\r\n if (!taskId) {\r\n return false;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n return storedUnread.includes(taskId.toString());\r\n}\r\n\r\nfunction storageSaveSpotfixVersion (version) {\r\n localStorage.setItem('spotfix_app_version', `${version}`);\r\n}\r\n\r\nfunction clearLocalstorageOnLogout () {\r\n localStorage.removeItem('spotfix_email');\r\n localStorage.removeItem('spotfix_session_id');\r\n localStorage.removeItem('spotfix_user_id');\r\n localStorage.setItem('spotfix_widget_is_closed', '1');\r\n wsSpotfix.close();\r\n}\r\n\n/**\r\n * File uploader handler for managing file attachments with validation and upload capabilities\r\n */\r\nclass FileUploader {\r\n /**\r\n * Create a new FileUploader instance\r\n * @param {function} escapeHtmlHandler - Function to escape HTML strings for security\r\n */\r\n constructor(escapeHtmlHandler) {\r\n /** @type {Array<{id: string, file: File}>} */\r\n this.files = [];\r\n\r\n /** @type {number} Maximum allowed file size in bytes */\r\n this.maxFileSize = 5 * 1024 * 1024; // 5MB\r\n\r\n /** @type {number} Maximum total size for all files in bytes */\r\n this.maxTotalSize = 25 * 1024 * 1024; // 25MB\r\n\r\n /** @type {number} Maximum number of files allowed */\r\n this.maxFiles = 5;\r\n\r\n /** @type {string[]} Allowed MIME types for files */\r\n this.allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'text/plain', 'application/msword'];\r\n\r\n /** @type {function} HTML escaping function for XSS protection */\r\n this.escapeHtmlHandler = escapeHtmlHandler;\r\n\r\n /** @type {string[]} File size units for display */\r\n this.SIZE_UNITS = ['Bytes', 'KB', 'MB', 'GB'];\r\n }\r\n\r\n /**\r\n * Initialize elements and bindings. Should be called only for comments.\r\n * @returns {void}\r\n */\r\n init() {\r\n this.initializeElements();\r\n this.bindFilesInputChange();\r\n }\r\n\r\n /**\r\n * Define widget elements to work with uploader.\r\n * @returns {void}\r\n */\r\n initializeElements() {\r\n /** @type {HTMLInputElement|null} */\r\n this.fileInput = document.getElementById('doboard_task_widget__file-upload__file-input-button');\r\n\r\n /** @type {HTMLElement|null} */\r\n this.fileList = document.getElementById('doboard_task_widget__file-upload__file-list');\r\n\r\n this.uploaderWrapper = document.getElementById('doboard_task_widget__file-upload__wrapper');\r\n\r\n /** @type {HTMLElement|null} */\r\n this.errorMessage = document.getElementById('doboard_task_widget__file-upload__error');\r\n\r\n if (!this.fileInput || !this.fileList || !this.errorMessage || this.uploaderWrapper) {\r\n console.warn('File uploader elements not found');\r\n }\r\n }\r\n\r\n /**\r\n * Define hidden file input change to run uploader logic.\r\n * @returns {void}\r\n */\r\n bindFilesInputChange() {\r\n if (this.fileInput) {\r\n this.fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\r\n }\r\n }\r\n\r\n /**\r\n * Bind action to paperclip button.\r\n * @param {HTMLElement} element - The paperclip button element\r\n * @returns {void}\r\n */\r\n bindPaperClipAction(element) {\r\n element.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n if (this.fileInput) {\r\n this.fileInput.click();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Handle file input change event\r\n * @param {Event} event - File input change event\r\n * @returns {void}\r\n */\r\n handleFileInputChange(event) {\r\n this.clearError();\r\n\r\n const selectedFiles = Array.from(event.target.files);\r\n if (this.files.length + selectedFiles.length > this.maxFiles) {\r\n this.showError(`Maximum ${this.maxFiles} files can be attached.`);\r\n return;\r\n }\r\n const validFiles = selectedFiles.filter(file => this.validateFile(file));\r\n\r\n validFiles.forEach(file => this.addFile(file));\r\n\r\n // Reset input to allow selecting same files again\r\n event.target.value = '';\r\n\r\n // show wrapper\r\n this.uploaderWrapper.style.display = 'block';\r\n }\r\n\r\n /**\r\n * Validate a file against upload constraints\r\n * @param {File} file - File to validate\r\n * @returns {boolean} True if file is valid, false otherwise\r\n */\r\n validateFile(file) {\r\n // Check file size\r\n if (file.size > this.maxFileSize) {\r\n this.showError(`File \"${file.name}\" is too large. Maximum size: ${this.formatFileSize(this.maxFileSize)}`);\r\n return false;\r\n }\r\n\r\n // Check total size\r\n const totalSize = this.getTotalSize() + file.size;\r\n if (totalSize > this.maxTotalSize) {\r\n this.showError(`Total files size exceeded. Maximum: ${this.formatFileSize(this.maxTotalSize)}`);\r\n return false;\r\n }\r\n\r\n // Check file type\r\n if (this.allowedTypes.length > 0 && !this.allowedTypes.includes(file.type)) {\r\n this.showError(`File type \"${file.type}\" for \"${file.name}\" is not supported.`);\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Calculate total size of all files\r\n * @returns {number} Total size in bytes\r\n */\r\n getTotalSize() {\r\n return this.files.reduce((sum, fileData) => sum + fileData.file.size, 0);\r\n }\r\n\r\n /**\r\n * Add a file to the upload queue\r\n * @param {File} file - File to add\r\n * @returns {void}\r\n */\r\n addFile(file) {\r\n const fileWithId = {\r\n id: this.generateFileId(),\r\n file: file\r\n };\r\n\r\n this.files.push(fileWithId);\r\n this.renderFileList();\r\n }\r\n\r\n /**\r\n * Generate a unique file ID\r\n * @returns {string} Unique file identifier\r\n * @private\r\n */\r\n generateFileId() {\r\n return Date.now() + Math.random().toString(36).substr(2, 9);\r\n }\r\n\r\n /**\r\n * Remove a file from the upload queue\r\n * @param {string} fileId - ID of the file to remove\r\n * @returns {void}\r\n */\r\n removeFile(fileId) {\r\n this.files = this.files.filter(f => f.id !== fileId);\r\n this.renderFileList();\r\n this.clearError();\r\n }\r\n\r\n /**\r\n * Render the file list in the UI\r\n * @returns {void}\r\n */\r\n renderFileList() {\r\n if (!this.fileList) return;\r\n\r\n if (this.files.length === 0) {\r\n this.fileList.innerHTML = ksesFilter('No files attached
');\r\n return;\r\n }\r\n\r\n const fileItems = this.files.map(fileData => this.createFileItem(fileData));\r\n this.fileList.innerHTML = ksesFilter('');\r\n fileItems.forEach(item => this.fileList.appendChild(item));\r\n }\r\n\r\n /**\r\n * Create file item element for display\r\n * @param {object} fileData - File data object\r\n * @param {string} fileData.id - File identifier\r\n * @param {File} fileData.file - File object\r\n * @returns {HTMLDivElement} File item DOM element\r\n */\r\n createFileItem(fileData) {\r\n const { file, id } = fileData;\r\n const fileItem = document.createElement('div');\r\n fileItem.className = 'doboard_task_widget__file-upload__file-item';\r\n\r\n fileItem.innerHTML = ksesFilter(`\r\n \r\n × \r\n `);\r\n\r\n const removeBtn = fileItem.querySelector('.doboard_task_widget__file-upload__remove-btn');\r\n removeBtn.addEventListener('click', () => this.removeFile(id));\r\n\r\n return fileItem;\r\n }\r\n\r\n /**\r\n * Format file size for display\r\n * @param {number} bytes - File size in bytes\r\n * @returns {string} Formatted file size string\r\n */\r\n formatFileSize(bytes) {\r\n if (bytes === 0) return '0 Bytes';\r\n\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + this.SIZE_UNITS[i];\r\n }\r\n\r\n /**\r\n * Show uploader error message\r\n * @param {string} message - Error message to display\r\n * @returns {void}\r\n */\r\n showError(message) {\r\n if (this.errorMessage) {\r\n this.errorMessage.textContent = message;\r\n this.errorMessage.style.display = 'block';\r\n }\r\n }\r\n\r\n /**\r\n * Clear uploader error message\r\n * @returns {void}\r\n */\r\n clearError() {\r\n if (this.errorMessage) {\r\n this.errorMessage.textContent = '';\r\n this.errorMessage.style.display = 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Check if there are files to send\r\n * @returns {boolean} True if files are present, false otherwise\r\n */\r\n hasFiles() {\r\n return this.files.length > 0;\r\n }\r\n\r\n /**\r\n * Clear all files from upload queue\r\n * @returns {void}\r\n */\r\n clearFiles() {\r\n this.files = [];\r\n this.renderFileList();\r\n }\r\n\r\n /**\r\n * Validate file data structure before upload\r\n * @param {object} fileData - File data object to validate\r\n * @param {string} fileData.sessionId - Session identifier\r\n * @param {object} fileData.params - Additional parameters\r\n * @param {string} fileData.params.accountId - Account identifier\r\n * @param {string} fileData.params.projectToken - Project token\r\n * @param {string} fileData.commentId - Comment identifier\r\n * @param {string} fileData.fileName - File name\r\n * @param {File} fileData.fileBinary - File binary data\r\n * @returns {object} Validated file data\r\n * @throws {Error} When file data validation fails\r\n */\r\n validateFileData(fileData) {\r\n const validations = [\r\n { field: 'sessionId', type: 'string', message: 'No valid session found.' },\r\n { field: 'params.accountId', type: 'string', message: 'No valid account ID found.' },\r\n { field: 'params.projectToken', type: 'string', message: 'No valid project token found.' },\r\n { field: 'commentId', type: 'string', message: 'No valid commentId found.' },\r\n { field: 'fileName', type: 'string', message: 'No valid filename found.' }\r\n ];\r\n\r\n for (const validation of validations) {\r\n const value = this.getNestedValue(fileData, validation.field);\r\n if (!value || typeof value !== validation.type) {\r\n throw new Error(validation.message);\r\n }\r\n }\r\n\r\n if (!fileData.fileBinary || !(fileData.fileBinary instanceof File)) {\r\n throw new Error('No valid file object found.');\r\n }\r\n\r\n return fileData;\r\n }\r\n\r\n /**\r\n * Helper to get nested object values\r\n * @param {object} obj - Object to traverse\r\n * @param {string} path - Dot notation path to value\r\n * @returns {*} Value at the specified path\r\n * @private\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => current?.[key], obj);\r\n }\r\n\r\n /**\r\n * Send single file attachment\r\n * @param {object} fileData - File data for upload\r\n * @returns {Promise} Upload response\r\n */\r\n async sendSingleAttachment(fileData) {\r\n const validatedFileData = await this.validateFileData(fileData);\r\n return await attachmentAddDoboard(validatedFileData);\r\n }\r\n\r\n /**\r\n * Send all attachments for a comment\r\n * @param {object} params - Upload parameters\r\n * @param {string} sessionId - Session identifier\r\n * @param {string} commentId - Comment identifier\r\n * @returns {Promise} Upload results\r\n */\r\n async sendAttachmentsForComment(params, sessionId, commentId) {\r\n /** @type {object} */\r\n const results = {\r\n preparedFilesCount: this.files.length,\r\n sentFilesCount: 0,\r\n fileResults: [],\r\n success: true\r\n };\r\n\r\n for (let i = 0; i < this.files.length; i++) {\r\n const fileData = this.files[i];\r\n /** @type {object} */\r\n const result = {\r\n success: false,\r\n response: null,\r\n error: null\r\n };\r\n\r\n try {\r\n const attachmentData = {\r\n params,\r\n sessionId,\r\n commentId,\r\n fileName: fileData.file.name,\r\n fileBinary: fileData.file,\r\n attachmentOrder: i\r\n };\r\n\r\n const response = await this.sendSingleAttachment(attachmentData);\r\n result.response = response;\r\n result.success = response.status === 200;\r\n\r\n if (result.success) {\r\n results.sentFilesCount++;\r\n }\r\n } catch (error) {\r\n result.error = error.message;\r\n }\r\n\r\n results.fileResults.push(result);\r\n }\r\n\r\n results.success = results.preparedFilesCount === results.sentFilesCount;\r\n this.clearFiles();\r\n\r\n return results;\r\n }\r\n}\r\n\nclass SpotFixTemplatesLoader {\r\n static getTemplateCode(templateName) {\r\n const templateMethod = this[templateName];\r\n\r\n if (typeof templateMethod !== 'function') {\r\n throw new Error(`Template method '${templateName}' not found`);\r\n }\r\n\r\n let template = templateMethod.call(this).trim();\r\n\r\n return template;\r\n }\r\n\r\n static all_issues() {\r\n return `\r\n`;\r\n }\r\n\r\n static concrete_issue() {\r\n return `\r\n\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n`;\r\n }\r\n\r\n static concrete_issue_day_content() {\r\n return `\r\n\r\n
{{dayContentMonthDay}}
\r\n
{{dayContentMessages}}
\r\n {{statusFixedHtml}}\r\n
\r\n`;\r\n }\r\n\r\n static concrete_issue_messages() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static create_issue() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static list_issues() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static user_menu() {\r\n return `\r\n`;\r\n }\r\n\r\n static wrap() {\r\n return `\r\n`;\r\n }\r\n\r\n static wrap_review() {\r\n return `\r\n\r\n \r\nReview content \r\n `;\r\n }\r\n\r\n static fixedHtml() {\r\n return `Finished
`;\r\n }\r\n static fixedTaskHtml() {\r\n return `This issue already fixed
`;\r\n }\r\n\r\n}\r\n\nclass SpotFixSVGLoader {\r\n static loadSVG(svgName) {\r\n const svgMethod = this[svgName];\r\n\r\n if (typeof svgMethod !== 'function') {\r\n throw new Error(`Template method '${svgName}' not found`);\r\n }\r\n\r\n return svgMethod.call(this).trim();\r\n }\r\n\r\n static getAsRawSVG(svgName) {\r\n return this.loadSVG(svgName);\r\n }\r\n\r\n static getAsDataURI(svgName) {\r\n const svg = this.loadSVG(svgName);\r\n return this.svgToDataURI(svg);\r\n }\r\n\r\n static svgToDataURI(svgString) {\r\n const bytes = new TextEncoder().encode(svgString);\r\n const baseBtoa = btoa(String.fromCharCode(...bytes));\r\n return `data:image/svg+xml;base64,${baseBtoa}`;\r\n }\r\n\r\n static chevronBack() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static chevronBackDark() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static buttonCloseScreen() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static buttonSendMessage() {\r\n return `\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n }\r\n\r\n static buttonPaperClip() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static logoDoBoardGreen() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static logoDoBoardWrap() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotPublic() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotPrivate() {\r\n return `\r\n\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotWidgetWrapPencil() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconLinkChain() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconEllipsesMore() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconAvatar() {\r\n return `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n }\r\n\r\n static iconEye() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconDoor() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconPlus() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconMaximize() {\r\n return `\r\n\r\n\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconMarker() {\r\n return ` `;\r\n }\r\n}\r\n\nclass SpotFixSourcesLoader {\r\n\r\n constructor() {\r\n this.loadAll();\r\n }\r\n\r\n getCSSCode() {\r\n // global gulp wrapper var\r\n return spotFixCSS;\r\n }\r\n\r\n loadAll() {\r\n this.loadFonts();\r\n this.loadCSS();\r\n };\r\n\r\n loadFonts() {\r\n const preconnect_first = document.createElement('link');\r\n preconnect_first.rel = 'preconnect';\r\n preconnect_first.href = 'https://fonts.googleapis.com';\r\n document.head.appendChild(preconnect_first);\r\n\r\n const preconnect_second = document.createElement('link');\r\n preconnect_second.rel = 'preconnect';\r\n preconnect_second.href = 'https://fonts.gstatic.com';\r\n preconnect_second.crossOrigin = 'crossorigin';\r\n document.head.appendChild(preconnect_second);\r\n\r\n const fontLink = document.createElement('link');\r\n fontLink.rel = 'stylesheet';\r\n fontLink.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap';\r\n document.head.appendChild(fontLink);\r\n }\r\n\r\n loadCSS() {\r\n const style = document.createElement('style');\r\n style.setAttribute('id', 'spotfix_css');\r\n style.textContent = this.getCSSCode();\r\n document.head.appendChild(style);\r\n }\r\n}\r\n\ndocument.dispatchEvent(new CustomEvent('spotFixLoaded', {\r\n detail: {\r\n timestamp: new Date().toISOString(),\r\n message: 'All scripts loaded successfully'\r\n }\r\n}));\r\n"],"names":["INDEXED_DB_NAME","indexedDBVersion","TABLE_USERS","TABLE_TASKS","TABLE_COMMENTS","LOCAL_DATA_BASE_TABLE","name","keyPath","async","openIndexedDB","version","Promise","resolve","reject","request","indexedDB","open","onsuccess","result","onerror","error","onupgradeneeded","deleteDB","db","await","window","databases","deleteReq","deleteDatabase","err","console","warn","spotfixIndexedDB","getIndexedDBName","localStorage","getItem","init","sessionId","projectToken","needInit","dbName","e","target","forEach","store","objectStoreNames","contains","item","createObjectStore","createIndex","missingStores","filter","length","close","newVersion","upgradeRequest","db2","e2","withStore","table","mode","callback","transaction","objectStore","oncomplete","put","data","Array","isArray","delete","key","clearTable","clear","clearPut","getAll","indexName","value","let","undefined","index","getTable","deleteTable","SPOTFIX_DOBOARD_API_URL","spotfixApiCall","method","accountId","Error","formData","FormData","hasOwnProperty","append","endpointUrl","URL","response","fetch","body","networkError","message","responseBody","json","parseError","operation_status","errorMessage","operation_message","userConfirmEmailDoboard","emailConfirmationToken","email_confirmation_token","encodeURIComponent","session_id","userId","user_id","email","accounts","operationStatus","createTaskDoboard","taskDetails","project_token","project_id","projectId","taskTitle","comment","taskDescription","meta","taskMeta","task_type","taskId","task_id","createTaskCommentDoboard","status","commentId","comment_id","attachmentAddDoboard","fileData","params","account_id","filename","fileName","file","fileBinary","attachment_order","attachmentOrder","registerUserDoboard","nickname","pageURL","confirmation_url","botDetectorData","JSON","parse","bot_detector_event_token","accountExists","user_email_confirmed","operationMessage","userEmailConfirmed","loginUserDoboard","password","logoutUserDoboard","includes","clearLocalstorageOnLogout","getTasksDoboard","tasks","map","task","taskLastUpdate","updated","taskCreated","created","taskCreatorTaskUser","creator_user_id","taskStatus","storageSaveTasksCount","getTasksCommentsDoboard","comments","commentBody","commentDate","issueTitle","task_name","getUserDoboard","users","userUpdateDoboard","timezone","timestamp","success","getReleaseVersion","tag_name","storageSaveSpotfixVersion","socket","heartbeatInterval","WS_URL","getSessionId","buildMessage","channel","action","wsSpotfix","connect","readyState","WebSocket","OPEN","onopen","setInterval","send","onmessage","event","object","onclose","code","reason","clearInterval","stringify","unsubscribe","subscribe","SPOTFIX_VERSION","confirmUserEmail","pendingTaskRaw","setItem","pendingTask","selectedText","description","selectedData","createdTask","handleCreateTask","removeItem","getTasksFullDetails","currentActiveTaskId","find","getUserDetails","currentUserId","user","sign","location","href","addTaskComment","commentText","getUserTasks","getAllTasks","formatDate","dateStr","date","time","dateObj","Date","replace","isNaN","getTime","offsetMinutes","getTimezoneOffset","localDateObj","getMonth","getDate","getHours","toString","padStart","getMinutes","getTaskAuthorDetails","taskAuthorAvatarImgSrc","taskAuthorName","element","getIssuesCounterString","onPageSpotsCount","totalSpotsCount","getAvatarSrc","author","avatar","m","getAuthorName","trim","registerUser","userEmail","userName","then","document","querySelector","innerText","ksesFilter","classList","remove","getElementById","focus","userUpdate","showMessageCallback","catch","loginUser","userPassword","Intl","DateTimeFormat","resolvedOptions","timeZone","spotFixSplitUrl","url","u","domain","segments","reversed","host","pathname","split","Boolean","reverse","push","join","setToggleStatus","rootElement","toggle","checked","addEventListener","timer","setTimeout","hide","clearTimeout","checkLogInOutButtonsVisible","el","style","display","closest","changeSize","container","add","spotFixCSS","CleanTalkWidgetDoboard","widgetElement","savedIssuesQuantityOnPage","savedIssuesQuantityAll","allTasksData","srcVariables","constructor","type","this","buttonCloseScreen","SpotFixSVGLoader","getAsDataURI","iconEllipsesMore","iconPlus","iconMaximize","chevronBack","buttonPaperClip","buttonSendMessage","logoDoBoardGreen","logoDoBoardWrap","iconSpotWidgetWrapPencil","iconMarker","iconSpotPublic","iconSpotPrivate","iconLinkChain","fileUploader","FileUploader","escapeHtml","getParams","urlParams","URLSearchParams","search","emailToken","get","newUrl","storageSetWidgetIsClosed","history","replaceState","title","registrationShowMessage","isWidgetClosed","taskHasSiteOwnerUpdate","storageTasksHasUnreadUpdates","checkIfTasksHasSiteOwnerUpdates","storageSaveTasksUpdateData","storageWidgetCloseIsSet","createWidgetElement","bindWidgetInputsInteractive","script","src","Object","fromEntries","searchParams","entries","bindCreateTaskEvents","submitButton","taskTitleElement","taskDescriptionElement","loginSectionElement","userEmailElement","userNameElement","userPasswordElement","borderColor","disabled","submitTaskResult","submitTask","cursor","needToLogin","isPublic","hideContainersSpinner","showOnlyCurrentPage","widgetContainer","createElement","className","innerHTML","removeAttribute","templateName","tasksFullDetails","templateVariables","config","SpotfixWidgetConfig","type_name","currentDomain","hostname","storageGetUserIsDefined","storageGetWidgetIsClosed","position","Number","verticalPosition","spotfixVersion","iconEye","iconDoor","chevronBackDark","issueComments","issuesCounter","loadTemplate","appendChild","spotFixRemoveHighlights","selection","getSelection","sessionIdExists","spotFixScrollToNodePath","spotFixGetSelectedData","nodePath","positionWidgetContainer","getTaskCount","widgetElementClasses","currentTarget","spotFixOpenWidget","issuesQuantityOnPage","spotsToBeHighlighted","currentURL","sortedTasks","sort","a","b","aIsHere","i","elTask","taskMetaString","taskData","isFixed","taskFullDetails","avatarData","currentPageURL","taskNodePath","taskPublicStatusImgSrc","taskPublicStatusHint","getAvatarData","getTaskFullDetails","listIssuesTemplateVariables","taskLastMessage","lastMessageText","taskPageUrl","taskFormattedPageUrl","lastMessageTime","sanitizeNodePath","avatarCSSClass","avatarStyle","taskAuthorInitials","initialsClass","classUnread","elementBgCSSClass","statusFixedHtml","storageProvidedTaskHasUnreadUpdates","isSpotHaveToBeHighlighted","spotFixHighlightElements","bindIssuesClick","gitHubAppVersion","s","issueTitleElement","currentTaskData","String","origin","issuesCommentsContainer","protocol","contenerClasess","dayMessagesData","initIssuerID","storageRemoveUnreadUpdateForTaskID","userIsIssuer","commentUserId","commentAuthorAvatarSrc","commentAuthorName","commentData","commentTime","issueMessageClassOwner","daysWrapperHTML","day","messageId","currentDayMessages","dayMessagesWrapperHTML","localeCompare","currentMessageTemplateVariables","dayContentMonthDay","dayContentMessages","textarea","handleTextareaChange","contentContainer","scrollTo","top","scrollHeight","behavior","sendButton","widgetClass","preventDefault","input","newCommentResponse","alert","hasFiles","attachmentsSendResult","sendAttachmentsForComment","showError","toConsole","log","backToAllIssuesController","self","paperclipController","bindPaperClipAction","spotFixShowWidget","querySelectorAll","getAttribute","showOneTask","taskHighlightData","getTaskHighlightData","variables","template","SpotFixTemplatesLoader","getTemplateCode","placeholder","replacement","isPlaceholderInAttribute","imgFilter","replaceAll","escapedPlaceholder","RegExp","test","unsafe","tasksCountLS","tasksCount","taskCountElement","wrapElementWithSpotfixHighlight","newElement","cloneNode","wrapper","insertAdjacentElement","taskIdToSearch","currentTaskSpotData","accordionController","context","handleScroll","bind","handleResize","messageText","titleSpan","messageDiv","messageWrap","color","widget","widgetCreateIssue","widgetConcreteIssue","scrollY","viewportHeight","innerHeight","selectionAbsoluteTop","getBoundingClientRect","widgetHeight","offsetHeight","bottom","scrollTimeout","resizeTimeout","str","spotFixShowDelayTimeout","SPOTFIX_DEBUG","SPOTFIX_SHOW_DELAY","spotFixInit","SpotFixSourcesLoader","loadBotDetector","id","head","spotFixIsInsideWidget","node","nodeType","Node","ELEMENT_NODE","parentElement","spotFixDebugLog","spinners","getElementsByClassName","containerClassesToShow","containers","tasksDetails","lastComment","dt","avatarSrc","authorName","authorDetails","charAt","toUpperCase","isAnyTaskUpdated","updatedtasksIDS","currentStateOfTask","issuerId","storageCheckTaskUpdate","updatedTaskIDs","lastMessage","updatedTaskId","updatedTaskData","storageAddUnreadUpdateForTaskID","isSelectionCorrect","html","options","allowedTags","strong","em","ul","ol","li","p","br","span","blockquote","pre","div","img","label","button","details","summary","allowedAttrs","doc","DOMParser","parseFromString","childNodes","clean","tag","tagName","toLowerCase","link","alt","parentNode","insertBefore","textContent","attributes","attr","attrName","startsWith","sel","isWrapReviewWidgetExists","focusNode","anchorNode","SPOTFIX_SELECTION_TYPE_TEXT","SPOTFIX_SELECTION_TYPE_IMG","SPOTFIX_SELECTION_TYPE_ELEMENT","spotFixGetSelectionType","range","getRangeAt","commonAncestor","commonAncestorContainer","spotFixGetSelectedImage","startContainer","endContainer","hasTextContent","isTextNode","TEXT_NODE","isCollapsed","collapsed","rangeCount","selectionType","startSelectPosition","endSelectPosition","commonNode","commonNodeElement","startOffset","endOffset","spotFixCalculateNodePath","imgElement","selectedImage","from","children","indexOf","imageUrl","widgetInstance","elementsMap","Map","spot","spotFixIsValidNodePath","spotFixRetrieveNodeFromPath","has","set","spots","spotFixHighlightImageElement","spotFixHighlightNestedElement","spotFixHighlightTextInElement","tooltipTitleText","spotfixHighlightOpen","text","spotSelectedText","markers","startPos","parseInt","endPos","slice","marker","insertText","idClass","cls","path","scrollIntoView","block","spans","affectedParents","Set","elementSelectionClassName","parent","tooltip","firstChild","removeChild","normalize","imageSelectionClassName","every","isInteger","imgNode","createTreeWalker","NodeFilter","SHOW_ELEMENT","acceptNode","spotFixIsElementInRange","FILTER_ACCEPT","FILTER_REJECT","nextNode","startElement","spotFixGetElementFromNode","endElement","spotFixIsElementPartiallySelected","spotFixFindNearbyElements","elementRange","createRange","selectNode","compareBoundaryPoints","Range","START_TO_START","END_TO_END","elementRect","rangeRect","right","left","elements","previousElement","previousElementSibling","nextElement","nextElementSibling","sibling","previousSibling","unshift","shift","visible","storedTasks","count","currentLastUpdate","storedTask","storedUnread","escapeHtmlHandler","files","maxFileSize","maxTotalSize","maxFiles","allowedTypes","SIZE_UNITS","initializeElements","bindFilesInputChange","fileInput","fileList","uploaderWrapper","handleFileInputChange","click","clearError","selectedFiles","validateFile","addFile","size","formatFileSize","getTotalSize","reduce","sum","fileWithId","generateFileId","renderFileList","now","Math","random","substr","removeFile","fileId","f","fileItems","createFileItem","fileItem","bytes","floor","parseFloat","pow","toFixed","clearFiles","validateFileData","validation","field","getNestedValue","File","obj","current","sendSingleAttachment","validatedFileData","results","preparedFilesCount","sentFilesCount","fileResults","attachmentData","templateMethod","call","all_issues","concrete_issue","concrete_issue_day_content","concrete_issue_messages","create_issue","list_issues","user_menu","wrap","wrap_review","fixedHtml","fixedTaskHtml","loadSVG","svgName","svgMethod","getAsRawSVG","svg","svgToDataURI","svgString","TextEncoder","encode","btoa","fromCharCode","iconAvatar","loadAll","getCSSCode","loadFonts","loadCSS","preconnect_first","preconnect_second","rel","fontLink","crossOrigin","setAttribute","dispatchEvent","CustomEvent","detail","toISOString"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"doboard-widget-bundle.min.js","sources":["doboard-widget-bundle.js"],"sourcesContent":["const INDEXED_DB_NAME = 'spotfix-localDB';\r\nconst indexedDBVersion = 1;\r\n\r\nconst TABLE_USERS = 'users';\r\nconst TABLE_TASKS = 'tasks';\r\nconst TABLE_COMMENTS = 'comments';\r\n\r\nconst LOCAL_DATA_BASE_TABLE = [\r\n {name: TABLE_USERS, keyPath: 'user_id'},\r\n {name: TABLE_TASKS, keyPath: 'taskId'},\r\n {name: TABLE_COMMENTS, keyPath: 'commentId'},\r\n];\r\n\r\nasync function openIndexedDB(name, version = indexedDBVersion) {\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(name, version);\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(request.error);\r\n request.onupgradeneeded = (e) => resolve(request.result);\r\n });\r\n}\r\n\r\nasync function deleteDB() {\r\n try {\r\n const dbs = await window.indexedDB.databases();\r\n for (const db of dbs) {\r\n await new Promise((resolve) => {\r\n const deleteReq = indexedDB.deleteDatabase(db.name);\r\n deleteReq.onsuccess = () => resolve();\r\n deleteReq.onerror = () => resolve();\r\n });\r\n }\r\n } catch (err) {\r\n console.warn('deleteDB error', err);\r\n }\r\n}\r\n\r\nconst spotfixIndexedDB = {\r\n getIndexedDBName: () =>\r\n `${INDEXED_DB_NAME}_${localStorage.getItem('spotfix_session_id') || localStorage.getItem('spotfix_project_token')}`,\r\n\r\n error: (request, error) => {\r\n console.error('IndexedDB error', request, error);\r\n },\r\n\r\n init: async () => {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n const projectToken = localStorage.getItem('spotfix_project_token');\r\n\r\n if (!sessionId && !projectToken) return { needInit: false };\r\n\r\n const dbName = spotfixIndexedDB.getIndexedDBName();\r\n\r\n await deleteDB();\r\n\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(dbName, indexedDBVersion);\r\n\r\n request.onupgradeneeded = (e) => {\r\n const db = e.target.result;\r\n LOCAL_DATA_BASE_TABLE.forEach((item) => {\r\n if (!db.objectStoreNames.contains(item.name)) {\r\n const store = db.createObjectStore(item.name, { keyPath: item.keyPath });\r\n if (item.name === TABLE_COMMENTS) store.createIndex('taskId', 'taskId');\r\n if (item.name === TABLE_TASKS) store.createIndex('userId', 'userId');\r\n }\r\n });\r\n resolve({ needInit: true });\r\n };\r\n\r\n request.onsuccess = (e) => {\r\n const db = e.target.result;\r\n const missingStores = LOCAL_DATA_BASE_TABLE.filter(\r\n (item) => !db.objectStoreNames.contains(item.name)\r\n );\r\n\r\n if (missingStores.length === 0) {\r\n db.close();\r\n resolve({ needInit: true });\r\n } else {\r\n const newVersion = db.version + 1;\r\n db.close();\r\n const upgradeRequest = indexedDB.open(dbName, newVersion);\r\n upgradeRequest.onupgradeneeded = (e2) => {\r\n const db2 = e2.target.result;\r\n missingStores.forEach((item) => {\r\n const store = db2.createObjectStore(item.name, { keyPath: item.keyPath });\r\n if (item.name === TABLE_COMMENTS) store.createIndex('taskId', 'taskId');\r\n if (item.name === TABLE_TASKS) store.createIndex('userId', 'userId');\r\n });\r\n };\r\n upgradeRequest.onsuccess = () => resolve({ needInit: true });\r\n upgradeRequest.onerror = (err) => reject(err);\r\n }\r\n };\r\n\r\n request.onerror = (err) => reject(err);\r\n });\r\n },\r\n\r\n withStore: async (table, mode = 'readwrite', callback) => {\r\n const dbName = spotfixIndexedDB.getIndexedDBName();\r\n const db = await openIndexedDB(dbName, indexedDBVersion);\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const transaction = db.transaction(table, mode);\r\n const store = transaction.objectStore(table);\r\n\r\n const result = callback(store);\r\n\r\n transaction.oncomplete = () => {\r\n db.close();\r\n resolve(result);\r\n };\r\n transaction.onerror = (e) => {\r\n db.close();\r\n reject(e.target.error);\r\n };\r\n } catch (err) {\r\n db.close();\r\n reject(err);\r\n }\r\n });\r\n },\r\n\r\n put: async (table, data) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => {\r\n if (Array.isArray(data)) {\r\n data.forEach((item) => store.put(item));\r\n } else {\r\n store.put(data);\r\n }\r\n });\r\n },\r\n\r\n delete: async (table, key) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => {\r\n store.delete(key);\r\n });\r\n },\r\n\r\n clearTable: async (table) => {\r\n return spotfixIndexedDB.withStore(table, 'readwrite', (store) => store.clear());\r\n },\r\n\r\n clearPut: async (table, data) => {\r\n await spotfixIndexedDB.clearTable(table);\r\n await spotfixIndexedDB.put(table, data);\r\n },\r\n\r\n getAll: async (table, indexName, value) => {\r\n return spotfixIndexedDB.withStore(table, 'readonly', (store) => {\r\n return new Promise((resolve, reject) => {\r\n let request;\r\n if (indexName && value !== undefined) {\r\n request = store.index(indexName).getAll(value);\r\n } else {\r\n request = store.getAll();\r\n }\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(request.error);\r\n });\r\n });\r\n },\r\n\r\n getTable: async (table) => {\r\n if (!localStorage.getItem('spotfix_session_id') && !localStorage.getItem('spotfix_project_token')) return [];\r\n return spotfixIndexedDB.getAll(table);\r\n },\r\n\r\n deleteTable: async (table, key) => {\r\n return spotfixIndexedDB.delete(table, key);\r\n },\r\n};\r\n\nconst SPOTFIX_DOBOARD_API_URL = 'https://api.doboard.com';\r\n\r\n/**\r\n * Makes an API call to the DoBoard endpoint with form data\r\n *\r\n * @param {Object} data - The data to send in the request\r\n * @param {string} method - The API method to call\r\n * @param {string|number} accountId - Optional account ID for the endpoint\r\n *\r\n * @returns {Promise} The response data when operation_status is 'SUCCESS'\r\n */\r\nconst spotfixApiCall = async(data, method, accountId = undefined) => {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Data must be a valid object');\r\n }\r\n\r\n if (!method || typeof method !== 'string') {\r\n throw new Error('Method must be a valid string');\r\n }\r\n\r\n if (accountId !== undefined && (typeof accountId !== 'string' && typeof accountId !== 'number')) {\r\n throw new Error('AccountId must be a string or number');\r\n }\r\n\r\n const formData = new FormData();\r\n for (const key in data) {\r\n if (data.hasOwnProperty(key)) {\r\n if (data[key] !== undefined && data[key] !== null) {\r\n formData.append(key, data[key]);\r\n }\r\n }\r\n }\r\n\r\n let endpointUrl;\r\n if (accountId !== undefined) {\r\n endpointUrl = `${SPOTFIX_DOBOARD_API_URL}/${accountId}/${method}`;\r\n } else {\r\n endpointUrl = `${SPOTFIX_DOBOARD_API_URL}/${method}`;\r\n }\r\n\r\n try {\r\n new URL(endpointUrl);\r\n } catch (error) {\r\n throw new Error(`Invalid endpoint URL: ${endpointUrl}`);\r\n }\r\n\r\n let response;\r\n try {\r\n response = await fetch(endpointUrl, {\r\n method: 'POST',\r\n body: formData,\r\n });\r\n } catch (networkError) {\r\n throw new Error(`Network error: ${networkError.message}`);\r\n }\r\n\r\n let responseBody;\r\n try {\r\n responseBody = await response.json();\r\n } catch (parseError) {\r\n throw new Error('Failed to parse JSON response from server');\r\n }\r\n\r\n if (!responseBody || typeof responseBody !== 'object') {\r\n throw new Error('Invalid response format from server');\r\n }\r\n\r\n if (!responseBody.data) {\r\n throw new Error('Missing data field in server response');\r\n }\r\n\r\n if (!responseBody.data.operation_status) {\r\n throw new Error('Missing operation_status in response data');\r\n }\r\n\r\n if (responseBody.data.operation_status === 'FAILED') {\r\n const errorMessage = responseBody.data.operation_message || 'Operation failed without specific message';\r\n if(responseBody?.data?.operation_message === 'session_id Unknown'){\r\n clearLocalstorageOnLogout();\r\n checkLogInOutButtonsVisible();\r\n await deleteDB();\r\n }\r\n throw new Error(errorMessage);\r\n }\r\n\r\n if (responseBody.data.operation_status === 'SUCCESS') {\r\n return responseBody.data;\r\n }\r\n\r\n throw new Error(`Unknown operation status: ${responseBody.data.operation_status}`);\r\n}\r\n\r\nconst userConfirmEmailDoboard = async (emailConfirmationToken) => {\r\n const data = {\r\n email_confirmation_token: encodeURIComponent(emailConfirmationToken)\r\n }\r\n const result = await spotfixApiCall(data, 'user_confirm_email');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accounts: result.accounts,\r\n operationStatus: result.operation_status\r\n };\r\n};\r\n\r\nconst createTaskDoboard = async (sessionId, taskDetails) => {\r\n const accountId = taskDetails.accountId;\r\n const data = {\r\n session_id: sessionId,\r\n project_token: taskDetails.projectToken,\r\n project_id: taskDetails.projectId,\r\n user_id: localStorage.getItem('spotfix_user_id'),\r\n name: taskDetails.taskTitle,\r\n comment: taskDetails.taskDescription,\r\n meta: taskDetails.taskMeta,\r\n task_type: 'PUBLIC'\r\n }\r\n const result = await spotfixApiCall(data, 'task_add', accountId);\r\n return {\r\n taskId: result.task_id,\r\n }\r\n};\r\n\r\nconst createTaskCommentDoboard = async (accountId, sessionId, taskId, comment, projectToken, status = 'ACTIVE') => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n task_id: taskId,\r\n comment: comment,\r\n status: status\r\n }\r\n const result = await spotfixApiCall(data, 'comment_add', accountId);\r\n return {\r\n commentId: result.comment_id,\r\n };\r\n};\r\n\r\nconst attachmentAddDoboard = async (fileData) => {\r\n const accountId = fileData.params.accountId;\r\n const data = {\r\n session_id: fileData.sessionId,\r\n project_token: fileData.params.projectToken,\r\n account_id: fileData.params.accountId,\r\n comment_id: fileData.commentId,\r\n filename: fileData.fileName,\r\n file: fileData.fileBinary,\r\n attachment_order: fileData.attachmentOrder\r\n }\r\n const result = await spotfixApiCall(data, 'attachment_add', accountId);\r\n // @ToDo need to handle result?\r\n};\r\n\r\nconst registerUserDoboard = async (projectToken, accountId, email, nickname, pageURL) => {\r\n let data = {\r\n project_token: projectToken,\r\n account_id: accountId,\r\n confirmation_url: email,\r\n }\r\n if (email && nickname) {\r\n data.email = email;\r\n data.name = nickname;\r\n }\r\n\r\n if (localStorage.getItem('bot_detector_event_token')) {\r\n try {\r\n const botDetectorData = JSON.parse(localStorage.getItem('bot_detector_event_token'));\r\n if (botDetectorData?.value) {\r\n data.bot_detector_event_token = botDetectorData?.value;\r\n }\r\n } catch (error) {\r\n data.bot_detector_event_token = '';\r\n }\r\n }\r\n const result = await spotfixApiCall(data, 'user_registration');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accountExists: result.user_email_confirmed === 1,\r\n operationMessage: result.operation_message,\r\n operationStatus: result.operation_status,\r\n userEmailConfirmed: result.user_email_confirmed,\r\n accounts: result.accounts,\r\n };\r\n};\r\n\r\nconst loginUserDoboard = async (email, password) => {\r\n const data = {\r\n email: email,\r\n password: password,\r\n }\r\n const result = await spotfixApiCall(data, 'user_authorize');\r\n return {\r\n sessionId: result.session_id,\r\n userId: result.user_id,\r\n email: result.email,\r\n accountExists: result.user_email_confirmed === 1,\r\n operationMessage: result.operation_message,\r\n operationStatus: result.operation_status,\r\n userEmailConfirmed: result.user_email_confirmed,\r\n accounts: result.accounts\r\n }\r\n}\r\n\r\nconst forgotPasswordDoboard = async (email) => {\r\n const data = {\r\n email: email\r\n }\r\n return await spotfixApiCall(data, 'user_password_reset');\r\n}\r\n\r\n\r\nconst logoutUserDoboard = async (projectToken) => {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n const accountsString = localStorage.getItem('spotfix_accounts');\r\n const accounts = accountsString !== 'undefined' ? JSON.parse(accountsString || '[]') : [];\r\n const accountId = accounts.length > 0 ? accounts[0].account_id : 1;\r\n\r\n if(sessionId && accountId) {\r\n const data = {\r\n session_id: sessionId,\r\n };\r\n\r\n const email = localStorage.getItem('spotfix_email') || '';\r\n\r\n if (email && email.includes('spotfix_')) {\r\n data.project_token = projectToken;\r\n }\r\n\r\n const result = await spotfixApiCall(data, 'user_unauthorize', accountId);\r\n\r\n if (result.operation_status === 'SUCCESS') {\r\n await deleteDB();\r\n clearLocalstorageOnLogout();\r\n checkLogInOutButtonsVisible();\r\n }\r\n }\r\n}\r\n\r\nconst getTasksDoboard = async (projectToken, sessionId, accountId, projectId, userId) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n project_id: projectId,\r\n task_type: 'PUBLIC',\r\n status: 'ACTIVE,DONE',\r\n }\r\n if ( userId ) {\r\n data.user_id = userId;\r\n }\r\n const result = await spotfixApiCall(data, 'task_get', accountId);\r\n const tasks = result.tasks.map(task => ({\r\n taskId: task.task_id,\r\n taskTitle: task.name,\r\n userId: task.user_id,\r\n taskLastUpdate: task.updated,\r\n taskCreated: task.created,\r\n taskCreatorTaskUser: task.creator_user_id,\r\n taskMeta: task.meta,\r\n taskStatus: task.status,\r\n }));\r\n await spotfixIndexedDB.clearPut(TABLE_TASKS, tasks);\r\n storageSaveTasksCount(tasks);\r\n return tasks;\r\n}\r\n\r\n\r\nconst getTasksCommentsDoboard = async (sessionId, accountId, projectToken, status = 'ACTIVE') => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n status: status\r\n }\r\n const result = await spotfixApiCall(data, 'comment_get', accountId);\r\n const comments = result.comments.map(comment => ({\r\n taskId: comment.task_id,\r\n commentId: comment.comment_id,\r\n userId: comment.user_id,\r\n commentBody: comment.comment,\r\n commentDate: comment.updated,\r\n status: comment.status,\r\n issueTitle: comment.task_name,\r\n }));\r\n await spotfixIndexedDB.clearPut(TABLE_COMMENTS, comments);\r\n return comments;\r\n};\r\n\r\nconst getUserDoboard = async (sessionId, projectToken, accountId, userId) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n }\r\n if (userId) data.user_id = userId;\r\n\r\n const result = await spotfixApiCall(data, 'user_get', accountId);\r\n if (data.user_id) {\r\n await spotfixIndexedDB.put(TABLE_USERS, result.users);\r\n } else {\r\n await spotfixIndexedDB.clearPut(TABLE_USERS, result.users);\r\n }\r\n return result.users;\r\n\r\n // @ToDo Need to handle these two different answers?\r\n /*// Format 1: users inside data\r\n if (responseBody.data && responseBody.data.operation_status) {\r\n if (responseBody.data.operation_status === 'FAILED') {\r\n throw new Error(responseBody.data.operation_message);\r\n }\r\n if (responseBody.data.operation_status === 'SUCCESS') {\r\n if (Array.isArray(responseBody.data.users)) {\r\n return responseBody.data.users;\r\n }\r\n return [];\r\n }\r\n }\r\n // Format 2: users at the top level\r\n if (responseBody.operation_status) {\r\n if (responseBody.operation_status === 'FAILED') {\r\n throw new Error(responseBody.operation_message);\r\n }\r\n if (responseBody.operation_status === 'SUCCESS') {\r\n if (Array.isArray(responseBody.users)) {\r\n return responseBody.users;\r\n }\r\n return [];\r\n }\r\n }*/\r\n};\r\n\r\nconst userUpdateDoboard = async (projectToken, accountId, sessionId, userId, timezone) => {\r\n const data = {\r\n session_id: sessionId,\r\n project_token: projectToken,\r\n user_id: userId,\r\n timestamp: timezone\r\n }\r\n await spotfixApiCall(data, 'user_update', accountId);\r\n return {\r\n success: true\r\n };\r\n}\r\n\r\nconst getReleaseVersion = async () => {\r\n try {\r\n const res = await fetch('https://api.github.com/repos/CleanTalk/SpotFix/releases');\r\n const data = await res.json();\r\n\r\n if (data.length > 0 && data[0].tag_name) {\r\n storageSaveSpotfixVersion(data[0].tag_name);\r\n return data[0].tag_name;\r\n }\r\n\r\n return null;\r\n } catch (err) {\r\n return null;\r\n }\r\n};\r\n\r\n\nlet socket = null;\r\nlet heartbeatInterval = null;\r\n\r\nconst WS_URL = 'wss://ws.doboard.com';\r\n\r\nconst getSessionId = () => localStorage.getItem('spotfix_session_id');\r\n\r\nconst buildMessage = (action) => ({\r\n channel: `account:${localStorage.getItem('spotfix_company_id')}`,\r\n action,\r\n account_id: localStorage.getItem('spotfix_company_id'),\r\n session_id: getSessionId(),\r\n project_token: localStorage.getItem('spotfix_project_token'),\r\n});\r\n\r\nconst wsSpotfix = {\r\n connect() {\r\n if ((socket && socket.readyState === WebSocket.OPEN) || !getSessionId()) {\r\n return;\r\n }\r\n\r\n socket = new WebSocket(WS_URL);\r\n\r\n socket.onopen = () => {\r\n heartbeatInterval = setInterval(() => {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n socket.send('heartbeat');\r\n }\r\n }, 50 * 1000);\r\n wsSpotfix.send(buildMessage('SUBSCRIBE'));\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n if (event.data === 'heartbeat') {\r\n return;\r\n }\r\n\r\n try {\r\n const data = JSON.parse(event.data);\r\n\r\n switch (data.object) {\r\n case 'users':\r\n spotfixIndexedDB.put(TABLE_USERS, data.data);\r\n break;\r\n case 'tasks':\r\n if (data.data.status === 'REMOVED') {\r\n spotfixIndexedDB.delete(TABLE_TASKS, data.data.task_id);\r\n break;\r\n }\r\n spotfixIndexedDB.put(TABLE_TASKS, {\r\n taskId: data.data.task_id,\r\n taskTitle: data.data.name,\r\n userId: data.data.user_id,\r\n taskLastUpdate: data.data.updated,\r\n taskCreated: data.data.created,\r\n taskCreatorTaskUser: data.data.creator_user_id,\r\n taskMeta: data.data.meta,\r\n taskStatus: data.data.status,\r\n });\r\n break;\r\n\r\n case 'comments':\r\n if (data.data.status === 'REMOVED') {\r\n spotfixIndexedDB.delete(TABLE_COMMENTS, data.data.comment_id);\r\n break;\r\n }\r\n spotfixIndexedDB.put(TABLE_COMMENTS, {\r\n taskId: data.data.task_id,\r\n commentId: data.data.comment_id,\r\n userId: data.data.user_id,\r\n commentBody: data.data.comment,\r\n commentDate: data.data.updated,\r\n status: data.data.status,\r\n issueTitle: data.data.task_name,\r\n });\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n } catch (e) {\r\n console.warn('WS non-JSON message:', event.data);\r\n }\r\n };\r\n\r\n socket.onclose = (e) => {\r\n console.warn('WS closed:', e.code, e.reason);\r\n\r\n socket = null;\r\n\r\n if (heartbeatInterval) {\r\n clearInterval(heartbeatInterval);\r\n heartbeatInterval = null;\r\n }\r\n };\r\n\r\n socket.onerror = (e) => {\r\n console.error('WS error:', e);\r\n };\r\n },\r\n\r\n send(data) {\r\n if (!socket || socket.readyState !== WebSocket.OPEN) {\r\n console.warn('WebSocket is not connected');\r\n return;\r\n }\r\n socket.send(JSON.stringify(data));\r\n },\r\n\r\n close() {\r\n wsSpotfix.unsubscribe();\r\n socket?.close();\r\n },\r\n\r\n subscribe() {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n wsSpotfix.send(buildMessage('SUBSCRIBE'));\r\n }\r\n },\r\n\r\n unsubscribe() {\r\n if (socket?.readyState === WebSocket.OPEN) {\r\n wsSpotfix.send(buildMessage('UNSUBSCRIBE'));\r\n }\r\n },\r\n};\r\n\nconst SPOTFIX_VERSION = \"1.1.5\";\r\n\nlet spotFixCSS = `.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip::after{content:\"\";position:absolute;left:8%;top:100%;transform:translateX(-50%);pointer-events:none;background:0 0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #545b61;display:block}.doboard_task_widget-send_message_paperclip{position:relative}.doboard_task_widget-send_message_paperclip .doboard_task_widget-paperclip-tooltip{display:none;position:absolute;left:0;bottom:0;transform:translateX(-3%) translateY(-43px);background:#545b61;color:#FFF;border:none;border-radius:3px;padding:10px 16px;font-size:13px;line-height:1.4;z-index:100;min-width:220px;max-width:320px;text-align:left;pointer-events:none;text-transform:none}.doboard_task_widget-send_message_paperclip:hover .doboard_task_widget-paperclip-tooltip{display:block}.doboard_task_widget *{font-family:Inter,sans-serif;font-weight:400;font-size:14px;line-height:130%;color:#40484F}.doboard_task_widget-header *{color:#252A2F;margin:0}.doboard_task_widget-header-icons{display:flex}.doboard_task_widget a{text-decoration:underline;color:#2F68B7}.doboard_task_widget a:hover{text-decoration:none}.doboard_task_widget{position:fixed;right:50px;bottom:20px;z-index:9999;vertical-align:middle;transition:top .1s;transform:translateZ(0);-webkit-transform:translateZ(0);will-change:transform}.doboard_task_widget_cursor-pointer{cursor:pointer}.doboard_task_widget-container-maximize{width:80vw!important;max-width:1120px!important;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-container{width:430px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;-moz-flex-direction:column}@media (max-height:800px){.doboard_task_widget-container,.doboard_task_widget-container-maximize{max-height:calc(60vh - 40px)}}.doboard_task_widget-header{display:flex;height:41px;min-height:41px;padding:0 16px;background-color:#EBF0F4;border-radius:8px 8px 0 0;border:1px solid #BBC7D1;border-bottom:none;justify-content:space-between;align-items:center;color:#FFF}.doboard_task_widget-user_menu-header{display:flex;padding:16px;border:1px solid #BBC7D1;border-bottom-color:#EBF0F4;border-radius:8px 8px 0 0;flex-direction:column;align-items:center;color:#252A2F;background-color:#F3F6F9}.doboard_task_widget-user_menu-header-top{display:flex;height:fit-content;align-items:center;width:100%;justify-content:space-between}.doboard_task_widget-user_menu-header-avatar{max-width:60px;max-height:60px;width:60px;height:60px;border-radius:50%;margin-bottom:4px}.doboard_task_widget-user_menu-item{display:flex;align-items:center;border-bottom:1px #EBF0F4 solid;padding:0 16px;height:40px;margin-top:10px}.doboard_task_widget-content{flex:1;overflow-y:auto;background:#FFF;border-radius:0 0 8px 8px;border:1px #BBC7D1;border-style:none solid solid;box-shadow:0 4px 15px 8px #CACACA40;scrollbar-width:none;max-height:60vh}.doboard_task_widget-element-container{margin-bottom:30px}.doboard_task_widget-wrap{box-shadow:none;position:fixed;right:-50px;padding:0;cursor:pointer;width:69px;height:52px;border-top-left-radius:4px;border-bottom-left-radius:4px;background-color:rgba(255,255,255,.9);border:1px solid #EBF0F4;display:flex;align-items:center;justify-content:center}.doboard_task_widget-hidden,.doboard_task_widget-input-container.hidden,.doboard_task_widget-login.hidden,.doboard_task_widget-wrap.hidden,.wrap_review::after{display:none}.doboard_task_widget-wrap img{width:32px;height:32px;transform:scaleX(-1)}.wrap_review{width:164px;min-width:164px;height:54px}.wrap_review img{width:28px;height:28px;transform:scaleX(-1)}.wrap_review:hover{background-color:#fff}@media (max-width:480px){.doboard_task_widget-wrap{right:-20px}}#review_content_button_text{color:#D5991A;margin-left:6px;font-weight:600;font-size:14px;text-transform:none!important}#doboard_task_widget-task_count{position:absolute;top:-12px;right:4px;width:22px;height:22px;opacity:1;background:#ef8b43;border-radius:50%;color:#FFF;text-align:center;line-height:22px}#doboard_task_widget-task_count.hidden{width:0;height:0;opacity:0}.doboard_task_widget-input-container{position:relative;margin-bottom:24px}.doboard_task_widget-input-container .doboard_task_widget-field{padding:0 8px;border-radius:4px;border:1px solid #BBC7D1;outline:0!important;appearance:none;width:100%;height:40px;background:#FFF;color:#000;max-width:-webkit-fill-available;max-width:-moz-available}.doboard_task_widget-field:focus{border-color:#2F68B7}.doboard_task_widget-input-container textarea.doboard_task_widget-field{height:94px;padding-top:11px;padding-bottom:11px}.doboard_task_widget-field+label{color:#252A2F;background:#fff;position:absolute;top:20px;left:8px;transform:translateY(-50%);transition:all .2s ease-in-out}.doboard_task_widget-field.has-value+label,.doboard_task_widget-field:focus+label{font-size:10px;top:0;left:12px;padding:0 4px;z-index:5}.doboard_task_widget-field:focus+label{color:#2F68B7}.doboard_task_widget-login{background:#F9FBFD;border:1px solid #BBC7D1;border-radius:4px;padding:11px 8px 8px;margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-accordion{height:0;overflow:hidden;opacity:0;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-accordion{height:auto;overflow:visible;opacity:1}.doboard_task_widget-login .doboard_task_widget-input-container:last-child{margin-bottom:0}.doboard_task_widget-login .doboard_task_widget-login-icon{display:block;position:relative;padding-right:24px;cursor:pointer}.doboard_task_widget-login.active .doboard_task_widget-login-icon{margin-bottom:24px}.doboard_task_widget-login .doboard_task_widget-login-icon::after{position:absolute;top:0;right:4px;content:\"\";display:block;width:10px;height:10px;transform:rotate(45deg);border:2px solid #40484F;border-radius:1px;border-top:none;border-left:none;transition:all .2s ease-in-out}.doboard_task_widget-login.active .doboard_task_widget-login-icon::after{transform:rotate(-135deg);top:7px}.doboard_task_widget-login .doboard_task_widget-field+label,.doboard_task_widget-login .doboard_task_widget-input-container .doboard_task_widget-field{background:#F9FBFD}.doboard_task_widget-submit_button{min-height:48px;width:100%;max-width:400px;margin-bottom:10px;color:#FFF;background:#22A475;border:none;border-radius:6px;font-family:Inter,sans-serif;font-weight:700;font-size:16px;line-height:150%;cursor:pointer;transition:all .2s ease-in-out}.doboard_task_widget-submit_button:hover{background:#1C7857;color:#FFF}.doboard_task_widget-submit_button:disabled{background:rgba(117,148,138,.92);color:#FFF;cursor:wait}.doboard_task_widget-login-buttons-wrapper{display:flex;gap:10px;margin-bottom:10px}.doboard_task_widget-login-buttons-wrapper .doboard_task_widget-submit_button{margin-bottom:0;width:auto;min-height:32px;font-size:14px;padding:4px 12px}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page{flex:1;background:#FFF;border:1px solid #22A475;color:#22A475}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black:hover,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page:hover{background:#f0fdf4;color:#1C7857}.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-login_button,.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-restore_password_button{flex:2}.doboard_task_widget-issue-title{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doboard_task_widget-hidden_element{opacity:0}.doboard_task_widget-message-wrapper{border-radius:4px;padding:8px;margin-bottom:14px;display:grid;justify-items:center}.doboard_task_widget-error_message-wrapper.hidden,.doboard_task_widget-message-wrapper.hidden{display:none}.doboard_task_widget-error_message{background:#fdd;border:1px solid #cf6868}.doboard_task_widget-notice_message{background:#dde9ff;border:1px solid #68a6cf}#doboard_task_widget-error_message-header{font-weight:600}#doboard_task_widget-error_message{text-align:center}.doboard_task_widget-task_row{display:flex;max-height:55px;cursor:pointer;align-items:center;justify-content:space-between;padding:1px 15px}.doboard_task_widget-task_row:last-child{margin-bottom:0}.doboard_task_widget-task-text_bold{font-weight:700}.doboard_task_widget-element_selection,.doboard_task_widget-image_selection,.doboard_task_widget-text_selection,.doboard_task_widget-text_selection.image-highlight>img{background:rgba(208,213,127,.68)}.doboard_task_widget-issues_list_empty{text-align:center;margin:20px 0}.doboard_task_widget-avatar_container{display:flex;height:44px;width:44px;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:100%}.doboard_task_widget-comment_data_owner .doboard_task_widget-avatar_container{opacity:0}.doboard_task_widget-avatar_placeholder{min-height:44px;min-width:44px;border-radius:50%;font-size:24px;line-height:1.2083333333;padding:0;background:#1C7857;display:inline-grid;align-content:center;justify-content:center}.doboard_task_widget-avatar-initials{color:#FFF;width:inherit;text-align:center}.doboard_task_widget-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover}.doboard_task_widget-description_container{height:55px;width:calc(100% - 44px - 8px);border-bottom:1px solid #EBF0F4;display:block;margin-left:8px}.doboard_task_widget-task_row:last-child .doboard_task_widget-description_container{border-bottom:none}.doboard_task_widget-all_issues{padding-bottom:0}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{overflow:auto;max-height:85vh;display:none}.doboard_task_widget-task_last_message,.doboard_task_widget-task_page_url a,.doboard_task_widget-task_title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.doboard_task_widget-all_issues-container{scrollbar-width:none;margin-top:10px}.doboard_task_widget-content.doboard_task_widget-concrete_issue{padding:0}.doboard_task_widget-concrete_issues-container{padding:10px 16px 5px}.doboard_task_widget-all_issues-container::-webkit-scrollbar,.doboard_task_widget-all_issues::-webkit-scrollbar,.doboard_task_widget-concrete_issues-container::-webkit-scrollbar,.doboard_task_widget-content::-webkit-scrollbar{width:0}.doboard_task_widget-task_title{font-weight:700;display:flex;justify-content:space-between;align-items:center}.doboard_task_widget-task_title span{font-weight:700;display:inline-block}.doboard_task_widget-task_title-details{display:flex;max-width:calc(100% - 40px);align-items:center}.doboard_task_widget-task_title-unread_block{opacity:0;height:8px;width:8px;background:#f08c43;border-radius:50%;display:inline-block;font-size:8px;font-weight:600;position:relative}.doboard_task_widget-task_title-unread_block.unread{opacity:1}.doboard_task_widget-task_last_message{max-width:85%;height:36px}.doboard_task_widget-task_page_url{max-width:70%;height:36px;display:flex;align-items:center}.doboard_task_widget-task_page_url a{color:#40484F;text-decoration:none;margin-left:8px;max-width:100%}.doboard_task_widget-bottom{display:flex;justify-content:space-between}.doboard_task_widget-bottom-is-fixed{border-radius:10px;background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHZpZXdCb3g9IjAgMCAxOSAxOSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik03LjA4MTE5IDAuMjIzNDM0QzguOTkxNjkgLTAuMjA4MTY3IDEwLjk5MTMgLTAuMDExMjE5NCAxMi43ODA0IDAuNzg1OTM0QzEzLjE1ODQgMC45NTQ2MjQgMTMuMzI4NiAxLjM5ODAzIDEzLjE2MDMgMS43NzYxN0MxMi45OTE3IDIuMTU0MTkgMTIuNTQ4MiAyLjMyNDI0IDEyLjE3MDEgMi4xNTYwNUMxMC42NzY0IDEuNDkwNTIgOS4wMDcyNiAxLjMyNiA3LjQxMjI1IDEuNjg2MzJDNS44MTcxNyAyLjA0NjcxIDQuMzgwOTcgMi45MTI5NiAzLjMxODUgNC4xNTYwNUMyLjI1NjIzIDUuMzk5MDEgMS42MjQ0MSA2Ljk1MjI5IDEuNTE2NzQgOC41ODM3OUMxLjQwOTI0IDEwLjIxNTQgMS44MzE4NCAxMS44MzkgMi43MjE4MiAxMy4yMTA3QzMuNjExNzkgMTQuNTgyMiA0LjkyMTY0IDE1LjYyOTQgNi40NTUyMSAxNi4xOTYxQzcuOTg5MDIgMTYuNzYyNiA5LjY2NTUzIDE2LjgxODkgMTEuMjMzNSAxNi4zNTUzQzEyLjgwMTYgMTUuODkxNiAxNC4xNzgzIDE0LjkzMzUgMTUuMTU3NCAxMy42MjM4QzE2LjEzNjQgMTIuMzE0MiAxNi42NjYxIDEwLjcyMjcgMTYuNjY3MSA5LjA4NzY5TDE4LjE2NzEgOS4wODg2N0MxOC4xNjU4IDExLjA0NzEgMTcuNTMxMiAxMi45NTM2IDE2LjM1ODUgMTQuNTIyM0MxNS4xODU5IDE2LjA5MDcgMTMuNTM3MyAxNy4yMzg0IDExLjY1OTMgMTcuNzkzN0M5Ljc4MTEgMTguMzQ5MSA3Ljc3MjkzIDE4LjI4MiA1LjkzNTY4IDE3LjYwMzNDNC4wOTg1IDE2LjkyNDYgMi41MjkxMiAxNS42NzAxIDEuNDYzMDMgMTQuMDI3MUMwLjM5NzAzNSAxMi4zODQxIC0wLjEwOTEwOSAxMC40Mzk1IDAuMDE5NjY4MyA4LjQ4NTE1QzAuMTQ4NjA3IDYuNTMwOCAwLjkwNjMyMyA0LjY3MDMzIDIuMTc4ODUgMy4xODE0NEMzLjQ1MTM2IDEuNjkyNjggNS4xNzA4OCAwLjY1NTE2MiA3LjA4MTE5IDAuMjIzNDM0WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPHBhdGggZD0iTTE2Ljg4NTkgMS44OTA0M0MxNy4xNzg2IDEuNTk3NTMgMTcuNjUzNCAxLjU5Nzg0IDE3Ljk0NjQgMS44OTA0M0MxOC4yMzkzIDIuMTgzMTYgMTguMjQwMSAyLjY1Nzk2IDE3Ljk0NzQgMi45NTA5N0w5LjYxMzQyIDExLjI5MjhDOS40NzI4MiAxMS40MzMzIDkuMjgxOTYgMTEuNTEyNCA5LjA4MzE1IDExLjUxMjVDOC44ODQzMiAxMS41MTI1IDguNjkzNDggMTEuNDMzMyA4LjU1Mjg3IDExLjI5MjhMNi4wNTI4NyA4Ljc5Mjc3QzUuNzYwMTQgOC40OTk5IDUuNzYwMTEgOC4wMjUwOCA2LjA1Mjg3IDcuNzMyMjJDNi4zNDU3MiA3LjQzOTM3IDYuODIwNTEgNy40Mzk0NiA3LjExMzQyIDcuNzMyMjJMOS4wODIxNyA5LjcwMDk3TDE2Ljg4NTkgMS44OTA0M1oiIGZpbGw9IiMyMkE0NzUiLz4NCjxwYXRoIGQ9Ik0xNy40MTcxIDcuNTcxMDlDMTcuODMxIDcuNTcxNDQgMTguMTY3IDcuOTA3MTYgMTguMTY3MSA4LjMyMTA5VjkuMDg4NjdMMTcuNDE3MSA5LjA4NzY5SDE2LjY2NzFWOC4zMjEwOUMxNi42NjcyIDcuOTA2OTQgMTcuMDAzIDcuNTcxMDkgMTcuNDE3MSA3LjU3MTA5WiIgZmlsbD0iIzIyQTQ3NSIvPg0KPC9zdmc+) 8px center no-repeat #EBFAF4;padding:4px 7px 4px 30px}.doboard_task_widget-bottom-is-fixed-task-block{text-align:center}.doboard_task_widget-bottom-is-fixed-task{background:#F3F6F9;color:#1C7857;display:inline-block;border-radius:10px;padding:5px 8px;margin:0 auto}.doboard_task_widget-task_row-green{background:#EBF0F4}.doboard_task_widget_return_to_all{display:flex;gap:8px;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:wrap}.doboard_task_widget-task_title-last_update_time{font-family:Inter,serif;font-weight:400;font-style:normal;font-size:11px;leading-trim:NONE;line-height:100%}.doboard_task_widget-task_title_public_status_img{opacity:50%;margin-left:5px;scale:90%}.doboard_task_widget-description-textarea{resize:none}.doboard_task_widget-switch_row{display:flex;align-items:center;gap:12px;margin:16px 0;justify-content:space-between}.doboard_task_widget-switch-label{font-weight:600;font-size:16px;height:24px;align-content:center}.doboard_task_widget-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}.doboard_task_widget-switch input{opacity:0;width:0;height:0}.doboard_task_widget-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:24px;transition:.2s}.doboard_task_widget-slider:before{position:absolute;content:\"\";height:20px;width:20px;left:2px;bottom:2px;background-color:#fff;border-radius:50%;transition:.2s}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider{background-color:#65D4AC}.doboard_task_widget-switch input:checked+.doboard_task_widget-slider:before{transform:translateX(20px)}.doboard_task_widget-switch-img{width:24px;height:24px;flex-shrink:0}.doboard_task_widget-switch-center{display:flex;gap:2px;flex-direction:column;-moz-flex-direction:column;flex:1 1 auto;min-width:0}.doboard_task_widget-switch-desc{display:block;font-size:12px;color:#707A83;margin:0;line-height:1.2;max-width:180px;word-break:break-word}.doboard_task_widget-concrete_issue-day_content{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-concrete_issue_day_content-month_day{text-align:center;font-weight:400;font-size:12px;line-height:100%;padding:8px;opacity:.75}.doboard_task_widget-concrete_issue_day_content-messages_wrapper{display:flex;flex-direction:column;-moz-flex-direction:column}.doboard_task_widget-comment_data_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;margin-bottom:15px;align-items:flex-end}.doboard_task_widget-comment_text_container{position:relative;width:calc(100% - 44px - 5px);height:auto;margin-left:5px;background:#F3F6F9;border-radius:16px}.doboard_task_widget-comment_text_container:after{content:\"\";position:absolute;bottom:0;left:-5px;width:13px;height:19px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAxMyAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuMTEyNTggMTkuMDMzNEM1LjI5NDg2IDE5LjgyMDEgMTAuNjEwNSAxNy45NzQxIDEyLjI3MTUgMTYuMTcxM0MxMi4yNzE1IDE2LjE3MTMgMTAuOTYyMyAtMi43ODEyNCA1LjA5NTU0IDAuMzQ5MDc5QzUuMDc0NCAxLjYxNDU0IDUuMDk1NTQgNS45OTQ5IDUuMDk1NTQgNi43NDA2OUM1LjA5NTU0IDE3LjA2NjIgLTAuODg0MDEyIDE4LjQ0MDEgMC4xMTI1OCAxOS4wMzM0WiIgZmlsbD0iI0YzRjZGOSIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container{background:#EBFAF4}.doboard_task_widget-comment_data_owner .doboard_task_widget-comment_text_container:after{left:auto;right:-5px;height:13px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTMiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMyAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjc3NzEgMTIuMzA2NkM3LjMzMTM1IDEzLjA5MzcgMS43NDU0NCAxMS4yNDY5IDAgOS40NDMxOUw3LjM5MTYgMEM3LjM5MTYgMTAuMzMwMyAxMy44MjQ0IDExLjcxMzEgMTIuNzc3MSAxMi4zMDY2WiIgZmlsbD0iI0VCRkFGNCIvPgo8L3N2Zz4K)}.doboard_task_widget-comment_body,.doboard_task_widget-comment_time{position:relative;z-index:1}.doboard_task_widget-comment_body{padding:6px 8px;min-height:30px}.doboard_task_widget-comment_body strong{font-variation-settings:\"wght\" 700}.doboard_task_widget-comment_body blockquote{margin:0;border-left:3px solid #22a475}.doboard_task_widget-comment_body blockquote p{margin:0 10px}.doboard_task_widget-comment_body details .mce-accordion-body{padding-left:20px}.doboard_task_widget-comment_body details .mce-accordion-summary{background:url(\"data:image/svg+xml;charset=utf-8,%3Csvg transform='rotate(180 0 0)' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E\") 0 no-repeat;padding-left:20px}.doboard_task_widget-comment_body .mce-accordion[open] .mce-accordion-summary{background:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' style='enable-background:new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M10 13.3c-.2 0-.4-.1-.6-.2l-5-5c-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0l4.4 4.4 4.4-4.4c.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2l-5 5c-.2.2-.4.2-.6.2z'/%3E%3C/svg%3E\") 0 no-repeat}.doboard_task_widget-comment_body details .mce-accordion-summary::marker{content:\"\"}.doboard_task_widget-comment_body pre{border:1px solid #d6dde3;border-left-width:8px;border-radius:4px;padding:13px 16px 14px 12px;white-space:pre-wrap}.doboard_task_widget-comment_time{font-weight:400;font-size:11px;opacity:.8;position:absolute;bottom:6px;right:6px}.doboard_task_widget-comment_body-img-strict{max-width:-webkit-fill-available;height:100px;margin-right:5px}.doboard_task_widget-send_message{padding:14px 10px;border-top:1px solid #BBC7D1;position:sticky;background:#fff;bottom:0;z-index:4}.doboard_task_widget-send_message_elements_wrapper{display:flex;flex-direction:row;-moz-flex-direction:row;align-content:center;flex-wrap:nowrap;justify-content:space-between;align-items:end}.doboard_task_widget-send_message_elements_wrapper button{height:37px;background:0 0;margin:0}.doboard_task_widget-send_message_elements_wrapper img{margin:0}.doboard_task_widget-send_message_input_wrapper{position:relative;display:inline-grid;align-items:center;justify-items:center;flex-grow:1;padding:0 6px}.doboard_task_widget-send_message_input_wrapper textarea{position:relative;width:100%;height:37px;border:none;outline:0;box-shadow:none;border-radius:24px;background:#F3F6F9;resize:none;margin-bottom:0!important;transition:height .2s ease-in-out;padding:8px;box-sizing:border-box}.doboard_task_widget-send_message_input_wrapper textarea.high{height:170px}.doboard_task_widget-send_message_input_wrapper textarea:focus{background:#F3F6F9;border-color:#007bff;outline:0}.doboard_task_widget-send_message_button,.doboard_task_widget-send_message_paperclip{display:inline-grid;border:none;background:0 0;cursor:pointer;padding:0;align-items:center;margin:0}.doboard_task_widget-send_message_button:hover,.doboard_task_widget-send_message_paperclip:hover rect{fill:#45a049}.doboard_task_widget-send_message_button:active,.doboard_task_widget-send_message_paperclip:active{transform:scale(.98)}.doboard_task_widget-spinner_wrapper_for_containers{display:flex;justify-content:center;align-items:center;min-height:60px;width:100%}.doboard_task_widget-spinner_for_containers{width:40px;height:40px;border-radius:50%;background:conic-gradient(transparent,#1C7857);mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#fff 0);animation:spin 1s linear infinite}.doboard_task_widget-create_issue{padding:10px}.doboard_task_widget__file-upload__wrapper{display:none;border:1px solid #BBC7D1;margin-top:14px;padding:0 10px 10px;border-radius:4px}.doboard_task_widget__file-upload__list-header{text-align:left;font-size:.9em;margin:5px 0;color:#444c529e}.doboard_task_widget__file-upload__file-input-button{display:none}.doboard_task_widget__file-upload__file-list{border:1px solid #ddd;border-radius:5px;padding:6px;max-height:200px;overflow-y:auto;background:#f3f6f9}.doboard_task_widget__file-upload__file-item{display:flex;justify-content:space-between;align-items:center;padding:4px;border-bottom:1px solid #bbc7d16b}.doboard_task_widget__file-upload__file-item:last-child{border-bottom:none}.doboard_task_widget__file-upload__file_info{display:inline-flex;align-items:center}.doboard_task_widget__file-upload__file-name{font-weight:700;font-size:.9em}.doboard_task_widget__file-upload__file-item-content{width:100%}.doboard_task_widget__file-upload__file_size{color:#666;font-size:.8em;margin-left:6px}.doboard_task_widget__file-upload__remove-btn{background:#22a475;color:#fff;border:none;border-radius:3px;cursor:pointer}.doboard_task_widget__file-upload__error{display:block;margin:7px 0 0;padding:7px;border-radius:4px;background:#fdd;border:1px solid #cf6868}.doboard_task_widget-show_button{position:fixed;background:#1C7857;color:#FFF;padding:8px 12px;border-radius:4px;font-size:14px;z-index:10000;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.3);transform:translate(-50%,-100%);margin-top:-8px;white-space:nowrap;border:none;font-family:inherit}@keyframes spin{to{transform:rotate(1turn)}}@media (max-width:480px){.doboard_task_widget{position:fixed;right:0;top:auto;bottom:0;margin:0 20px 20px;box-sizing:border-box;transform:translateZ(0);-moz-transform:translateZ(0);will-change:transform;max-height:90vh}.doboard_task_widget-header{padding:8px}.doboard_task_widget-issue-title{max-width:70px}.doboard_task_widget-container,.doboard_task_widget-container-maximize{width:100%;max-width:290px;margin:0 auto;max-height:90vh}.doboard_task_widget-content{height:auto;max-height:none;scrollbar-width:none}.doboard_task_widget-content::-webkit-scrollbar{display:none}.doboard_task_widget-all_issues-container,.doboard_task_widget-concrete_issues-container{max-height:80vh}}@supports (-webkit-overflow-scrolling:touch){.doboard_task_widget{position:fixed}}.doboard_task_widget_tasks_list{background-color:#fff;position:sticky;bottom:0;height:38px;display:flex;flex-direction:column-reverse;align-items:center;padding-bottom:8px}#doboard_task_widget-user_menu-logout_button{display:inline-flex;align-items:center}.doboard_task_widget-text_selection{position:relative;display:inline-block}.doboard_task_widget-see-task{cursor:pointer;text-decoration:underline}.doboard_task_widget-text_selection_tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:#FFF;color:#000;padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;z-index:9000;border:1px solid #BBC7D1;margin-bottom:8px}.doboard_task_widget-text_selection_tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#FFF}.doboard_task_widget-text_selection_tooltip::before{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#BBC7D1;z-index:-1}.doboard_task_widget-text_selection_tooltip_icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDEwMyAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMyAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMxNzcyNTA7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik01MywwSDB2MTAwaDMwLjJINTNDMTE5LjYsMTAwLDExOS42LDAsNTMsMHogTTMwLjIsMTAwYy0xNi42LDAtMzAtMTMuNC0zMC0zMHMxMy40LTMwLDMwLTMwDQoJYzE2LjYsMCwzMCwxMy40LDMwLDMwUzQ2LjgsMTAwLDMwLjIsMTAweiIvPg0KPC9zdmc+DQo=);background-repeat:no-repeat;width:22px;height:22px;margin:5px 3px}.doboard_task_widget-text_selection_tooltip_element{display:flex;justify-content:space-between}.toggle{position:relative;display:inline-block;width:46px;height:28px}.toggle input{opacity:0;width:0;height:0;position:absolute}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#bbc7d1;border-radius:24px;transition:.3s}.slider:before{content:\"\";position:absolute;height:24px;width:24px;left:2px;top:2px;background-color:#fff;border-radius:50%;transition:.3s}input:checked+.slider{background-color:#65d4ac}input:checked+.slider:before{transform:translateX(16px)}.doboard_task_widget-bottom-eye-icon,.doboard_task_widget-bottom-eye-off-icon{position:absolute;right:10px;top:50%;transform:translateY(-50%);width:20px;height:20px;cursor:pointer;border-radius:50%;transition:all .2s ease;z-index:10}.logout_button{font-weight:500;font-size:14px;color:#707A83;cursor:pointer}.doboard_task_widget-forgot_password,.doboard_task_widget-on_phantom_login_page,.doboard_task_widget-show_login_form{display:inline-block;cursor:pointer;color:#2F68B7;margin-bottom:0}.doboard_task_widget-forgot_password{margin-bottom:20px}.doboard_task_widget-login-is-invalid{color:red}.doboard_task_widget-forgot_password_form-menu,.doboard_task_widget-input-container-login-menu{margin:20px}.doboard_task_widget-bottom-eye-icon{background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMjAgMjAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDIwIDIwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBkPSJNMTAsMTcuNGMtNi4yLDAtOS43LTYuOC05LjgtNy4xYy0wLjEtMC4yLTAuMS0wLjUsMC0wLjdDMC4zLDkuNCwzLjgsMi42LDEwLDIuNmM2LjIsMCw5LjcsNi44LDkuOCw3LjENCgljMC4xLDAuMiwwLjEsMC41LDAsMC43QzE5LjcsMTAuNiwxNi4yLDE3LjQsMTAsMTcuNHogTTEuNywxMGMwLjgsMS4zLDMuNyw1LjksOC4zLDUuOWM0LjYsMCw3LjYtNC42LDguMy01LjkNCgljLTAuOC0xLjMtMy43LTUuOS04LjMtNS45QzUuNCw0LjEsMi40LDguNywxLjcsMTB6IE0xMCwxMy4zYy0xLjgsMC0zLjMtMS41LTMuMy0zLjNTOC4yLDYuOCwxMCw2LjhzMy4zLDEuNSwzLjMsMy4zDQoJUzExLjgsMTMuMywxMCwxMy4zeiBNMTAsOC4zQzksOC4zLDguMyw5LDguMywxMFM5LDExLjgsMTAsMTEuOHMxLjgtMC44LDEuOC0xLjhTMTEsOC4zLDEwLDguM3oiLz4NCjwvc3ZnPg0K) center center no-repeat #fff;background-size:16px 16px}.doboard_task_widget-bottom-eye-off-icon{background:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDIwIDIwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyMCAyMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE2LjgsMTMuMmMwLjEsMC4xLDAuMywwLjIsMC41LDAuMmMwLDAsMCwwLDAsMGMwLjIsMCwwLjQtMC4xLDAuNS0wLjNjMC43LTAuOSwxLjQtMS44LDEuOS0yLjgNCgljMC4xLTAuMiwwLjEtMC41LDAtMC43Yy0wLjEtMC4zLTMuNi03LjEtOS44LTcuMWMwLDAsMCwwLDAsMGMtMC42LDAtMS4zLDAuMS0xLjksMC4yQzcuOCwyLjksNy42LDMuMSw3LjUsMy4zczAsMC41LDAuMiwwLjcNCglMMTYuOCwxMy4yeiBNMTAsNC4xYzQuNiwwLDcuNiw0LjYsOC4zLDUuOWMtMC4zLDAuNS0wLjYsMS0xLDEuNUw5LjksNC4xQzkuOSw0LjEsMTAsNC4xLDEwLDQuMXogTTE5LjcsMTguNmwtNC4yLTQuMkw1LjYsNC41DQoJYzAsMCwwLDAsMCwwTDEuNCwwLjNDMS4xLDAsMC42LDAsMC4zLDAuM1MwLDEuMSwwLjMsMS40TDMuOSw1QzIuNCw2LjMsMS4xLDcuOSwwLjIsOS42Yy0wLjEsMC4yLTAuMSwwLjUsMCwwLjcNCgljMC4xLDAuMywzLjYsNy4xLDkuOSw3LjFjMS43LDAsMy40LTAuNSw0LjktMS41bDMuOCwzLjhjMC4xLDAuMSwwLjMsMC4yLDAuNSwwLjJzMC40LTAuMSwwLjUtMC4yQzIwLDE5LjQsMjAsMTguOSwxOS43LDE4LjZ6DQoJIE04LjMsOS40bDIuMywyLjNjLTAuMiwwLjEtMC40LDAuMS0wLjYsMC4xYy0wLjIsMC0wLjUsMC0wLjctMC4xYy0wLjItMC4xLTAuNC0wLjItMC42LTAuNGMtMC4yLTAuMi0wLjMtMC40LTAuNC0wLjYNCgljLTAuMS0wLjItMC4xLTAuNS0wLjEtMC43QzguMiw5LjgsOC4yLDkuNiw4LjMsOS40eiBNMTAsMTUuOWMtNC42LDAtNy42LTQuNi04LjMtNS45YzAuOS0xLjUsMi0yLjgsMy4zLTMuOWwyLjIsMi4yDQoJQzcuMSw4LjQsNyw4LjYsNyw4LjdDNi44LDkuMSw2LjcsOS42LDYuNywxMGMwLDAuNCwwLjEsMC45LDAuMiwxLjNjMC4yLDAuNCwwLjQsMC44LDAuNywxLjFjMC4zLDAuMywwLjcsMC42LDEuMSwwLjcNCgljMC40LDAuMiwwLjgsMC4yLDEuMywwLjJjMC40LDAsMC45LTAuMSwxLjMtMC4zYzAuMi0wLjEsMC4zLTAuMiwwLjUtMC4zbDIuMSwyLjFDMTIuNiwxNS41LDExLjMsMTUuOSwxMCwxNS45eiIvPg0KPC9zdmc+DQo=) center center no-repeat #fff;background-size:16px 16px;opacity:.5}`;\n\r\nasync function confirmUserEmail(emailConfirmationToken, params) {\r\n\tconst result = await userConfirmEmailDoboard(emailConfirmationToken);\r\n\t// Save session data to LS\r\n\tlocalStorage.setItem('spotfix_email', result.email);\r\n\tlocalStorage.setItem('spotfix_session_id', result.sessionId);\r\n\tlocalStorage.setItem('spotfix_user_id', result.userId);\r\n\tawait spotfixIndexedDB.init();\r\n\r\n\t// Get pending task from LS\r\n\tconst pendingTaskRaw = localStorage.getItem('spotfix_pending_task');\r\n\tif (!pendingTaskRaw) throw new Error('No pending task data');\r\n\r\n\tlet pendingTask;\r\n\ttry {\r\n\t\tpendingTask = JSON.parse(pendingTaskRaw);\r\n\t} catch (error) {\r\n\t\tthrow new Error('Invalid pending task data');\r\n\t}\r\n\r\n\t// Form taskDetails for task creation\r\n\tconst taskDetails = {\r\n\t\ttaskTitle: pendingTask.selectedText || 'New Task',\r\n\t\ttaskDescription: pendingTask.description || '',\r\n\t\tselectedData: pendingTask,\r\n\t\tprojectToken: params.projectToken,\r\n\t\tprojectId: params.projectId,\r\n\t\taccountId: params.accountId,\r\n\t\ttaskMeta: JSON.stringify(pendingTask)\r\n\t};\r\n\r\n\t// Create task\r\n\tconst createdTask = await handleCreateTask(result.sessionId, taskDetails);\r\n\t// Clear pending task\r\n\tlocalStorage.removeItem('spotfix_pending_task');\r\n\r\n\t// Return created task\r\n\treturn createdTask;\r\n}\r\n\r\nasync function getTasksFullDetails(params, tasks, currentActiveTaskId) {\r\n if (tasks.length > 0) {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\t\tawait getTasksCommentsDoboard(sessionId, params.accountId, params.projectToken);\r\n const comments = await spotfixIndexedDB.getAll(TABLE_COMMENTS);\r\n await getUserDoboard(sessionId, params.projectToken, params.accountId);\r\n\t\tconst users = await spotfixIndexedDB.getAll(TABLE_USERS);\r\n\t\tconst foundTask = tasks.find(item => +item.taskId === +currentActiveTaskId);\r\n\r\n return {\r\n comments: comments,\r\n users: users,\r\n\t\t\ttaskStatus: foundTask?.taskStatus,\r\n };\r\n }\r\n}\r\n\r\nasync function getUserDetails(params) {\r\n\t\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\t\tconst currentUserId = localStorage.getItem('spotfix_user_id');\r\n\t\tif(currentUserId) {\r\n\t\t\tawait getUserDoboard(sessionId, params.projectToken, params.accountId, currentUserId);\r\n\t\t\tconst users = await spotfixIndexedDB.getAll(TABLE_USERS);\r\n\t\t\treturn users.find(user => +user.user_id === +currentUserId) || {};\r\n\t\t}\r\n}\r\n\r\nasync function handleCreateTask(sessionId, taskDetails) {\r\n\ttry {\r\n\t\tconst result = await createTaskDoboard(sessionId, taskDetails);\r\n\t\tif (result && result.taskId && taskDetails.taskDescription) {\r\n const sign = `The spot has been posted at the following URL ${window.location.href} `;\r\n\t\t\tawait addTaskComment({\r\n\t\t\t\tprojectToken: taskDetails.projectToken,\r\n\t\t\t\taccountId: taskDetails.accountId\r\n\t\t\t}, result.taskId, taskDetails.taskDescription+sign);\r\n\t\t}\r\n\t\treturn result;\r\n\t} catch (err) {\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nasync function addTaskComment(params, taskId, commentText) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tif (!sessionId) throw new Error('No session');\r\n\tif (!params.projectToken || !params.accountId) throw new Error('Missing params');\r\n\treturn await createTaskCommentDoboard(params.accountId, sessionId, taskId, commentText, params.projectToken);\r\n}\r\n\r\nasync function getUserTasks(params) {\r\n\tif (!localStorage.getItem('spotfix_session_id')) {\r\n\t\treturn {};\r\n\t}\r\n\tconst projectToken = params.projectToken;\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst userId = localStorage.getItem('spotfix_user_id');\r\n\tawait getTasksDoboard(projectToken, sessionId, params.accountId, params.projectId, userId);\r\n\treturn await spotfixIndexedDB.getAll(TABLE_TASKS, 'userId', userId);\r\n}\r\n\r\nasync function getAllTasks(params) {\r\n\tif (!localStorage.getItem('spotfix_session_id')) {\r\n\t\treturn {};\r\n\t}\r\n\tconst projectToken = params.projectToken;\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tawait getTasksDoboard(projectToken, sessionId, params.accountId, params.projectId);\r\n\tconst tasksData = await spotfixIndexedDB.getAll(TABLE_TASKS);\r\n // Get only tasks with metadata\r\n\tconst filteredTaskData = tasksData.filter(task => {\r\n return task.taskMeta;\r\n });\r\n\r\n return filteredTaskData;\r\n}\r\n\r\nfunction formatDate(dateStr) {\r\n\t const months = [\r\n\t \t\"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\r\n\t \t\"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\r\n\t ];\r\n\t // dateStr expected format: 'YYYY-MM-DD HH:mm:ss' or 'YYYY-MM-DDTHH:mm:ssZ'\r\n\t if (!dateStr) return { date: '', time: '' };\r\n\t let dateObj;\r\n\t if (dateStr.includes('T')) {\r\n\t dateObj = new Date(dateStr);\r\n\t } else if (dateStr.includes(' ')) {\r\n\t dateObj = new Date(dateStr.replace(' ', 'T'));\r\n\t } else {\r\n\t dateObj = new Date(dateStr);\r\n\t }\r\n\t if (isNaN(dateObj.getTime())) return { date: '', time: '' };\r\n\r\n\t // Adjust to local timezone\r\n\t const offsetMinutes = dateObj.getTimezoneOffset();\r\n\t let localDateObj = new Date(dateObj.getTime() - offsetMinutes * 60000);\r\n\r\n\t const month = months[localDateObj.getMonth()];\r\n\t const day = localDateObj.getDate();\r\n\t const date = `${month} ${day}`;\r\n\t const hours = localDateObj.getHours().toString().padStart(2, '0');\r\n\t const minutes = localDateObj.getMinutes().toString().padStart(2, '0');\r\n\t const time = `${hours}:${minutes}`;\r\n\t return { date, time };\r\n}\r\n\r\nfunction getTaskAuthorDetails(params, taskId) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst mockUsersData =\r\n\t\t[\r\n\t\t\t{\r\n\t\t\t\t'taskId': '1',\r\n\t\t\t\t'taskAuthorAvatarImgSrc': 'https://s3.eu-central-1.amazonaws.com/cleantalk-ctask-atts/accounts/1/avatars/081a1b65d20fe318/m.jpg',\r\n\t\t\t\t'taskAuthorName': 'Test All Issues Single Author Name'\r\n\t\t\t}\r\n\t\t]\r\n\r\n\tconst defaultData =\r\n\t\t{\r\n\t\t\t'taskId': null,\r\n\t\t\t'taskAuthorAvatarImgSrc': null,\r\n\t\t\t'taskAuthorName': 'Task Author'\r\n\t\t};\r\n\r\n\tconst data = mockUsersData.find((element) => element.taskId === taskId);\r\n\treturn data === undefined ? defaultData : data;\r\n}\r\n\r\nfunction getIssuesCounterString(onPageSpotsCount, totalSpotsCount) {\r\n\treturn ` (${onPageSpotsCount}/${totalSpotsCount})`;\r\n}\r\n\r\n// Get the author's avatar\r\nfunction getAvatarSrc(author) {\r\n\tif (author && author.avatar) {\r\n\t\tif (typeof author.avatar === 'object' && author.avatar.m) {\r\n\t\t\treturn author.avatar.m;\r\n\t\t} else if (typeof author.avatar === 'string') {\r\n\t\t\treturn author.avatar;\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n}\r\n\r\n// Get the author's name\r\nfunction getAuthorName(author) {\r\n\tif (author) {\r\n\t\tif (author.name && author.name.trim().length > 0) {\r\n\t\t\treturn author.name;\r\n\t\t} else if (author.email && author.email.trim().length > 0) {\r\n\t\t\treturn author.email;\r\n\t\t}\r\n\t}\r\n\treturn 'Unknown Author';\r\n}\r\n\r\nfunction registerUser(taskDetails) {\r\n\tconst userEmail = taskDetails.userEmail;\r\n\tconst userName = taskDetails.userName;\r\n\tconst projectToken = taskDetails.projectToken;\r\n\tconst accountId = taskDetails.accountId;\r\n\tconst pageURL = taskDetails.selectedData.pageURL ? taskDetails.selectedData.pageURL : window.location.href;\r\n\r\n\tconst resultRegisterUser = (showMessageCallback) => registerUserDoboard(projectToken, accountId, userEmail, userName, pageURL)\r\n\t\t.then(response => {\r\n\t\t\tif (response.accountExists) {\r\n\t\t\t\tdocument.querySelector(\".doboard_task_widget-accordion>.doboard_task_widget-input-container\").innerText = ksesFilter('Account already exists. Please, login usin your password.');\r\n\t\t\t\tdocument.querySelector(\".doboard_task_widget-accordion>.doboard_task_widget-input-container.hidden\").classList.remove('hidden');\r\n\t\t\t\tdocument.getElementById(\"doboard_task_widget-user_password\").focus();\r\n\t\t\t} else if (response.sessionId) {\r\n\t\t\t\tlocalStorage.setItem('spotfix_session_id', response.sessionId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_user_id', response.userId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_email', response.email);\r\n\t\t\t\tlocalStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));\r\n\t\t\t\tspotfixIndexedDB.init();\r\n\t\t\t\tuserUpdate(projectToken, accountId);\r\n\t\t\t} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {\r\n\t\t\t\tif (response.operationMessage === 'Waiting for email confirmation') {\r\n\t\t\t\t\tresponse.operationMessage = 'Waiting for an email confirmation. Please check your Inbox.';\r\n\t\t\t\t\tif (document.getElementById('doboard_task_widget-error_message').innerText === 'Waiting for an email confirmation. Please check your Inbox.') {\r\n\t\t\t\t\t\tresponse.operationMessage = 'Incorrect email address. Please confirm your email to create the spot.';\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (typeof showMessageCallback === 'function') {\r\n\t\t\t\t\tshowMessageCallback(response.operationMessage, 'notice');\r\n\t\t\t\t}\r\n\t\t\t\tconst submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\t\t\t\t\tsubmitButton.disabled = true;\r\n\t\t\t\t\tsubmitButton.innerText = ksesFilter('Create spot');\r\n\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Session ID not found in response');\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tthrow error;\r\n\t\t});\r\n\r\n\t\treturn resultRegisterUser;\r\n}\r\n\r\nfunction loginUser(taskDetails) {\r\n\tconst userEmail = taskDetails.userEmail;\r\n\tconst userPassword = taskDetails.userPassword;\r\n\r\n\treturn (showMessageCallback) => loginUserDoboard(userEmail, userPassword)\r\n\t\t.then(response => {\r\n\t\t\tif (response.sessionId) {\r\n\t\t\t\tlocalStorage.setItem('spotfix_session_id', response.sessionId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_user_id', response.userId);\r\n\t\t\t\tlocalStorage.setItem('spotfix_email', response.email);\r\n\t\t\t\tlocalStorage.setItem('spotfix_email', userEmail);\r\n\t\t\t\tlocalStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));\r\n\t\t\t\tcheckLogInOutButtonsVisible();\r\n\t\t\t\tspotfixIndexedDB.init();\r\n\t\t\t} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {\r\n\t\t\t\tif (typeof showMessageCallback === 'function') {\r\n\t\t\t\t\tshowMessageCallback(response.operationMessage, 'notice');\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Session ID not found in response');\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tthrow error;\r\n\t\t});\r\n}\r\n\r\nfunction forgotPassword(userEmail) {\r\n\t\treturn (showMessageCallback) => forgotPasswordDoboard(userEmail)\r\n\t\t.then(response => {\r\n\t\t\tconsole.log('response ', response)\r\n\t\t\tif (response?.operation_status === 'SUCCESS') {\r\n\t\t\t\tshowMessageCallback('New password sent to email', 'notice');\r\n\t\t\t\tconst forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');\r\n\t\t\t\tconst loginContainer = document.getElementById('doboard_task_widget-input-container-login');\r\n\t\t\t\tconst submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\t\t\t\tif (forgotPasswordForm) {\r\n\t\t\t\t\tforgotPasswordForm.classList.add('doboard_task_widget-hidden');\r\n\t\t\t\t}\r\n\t\t\t\tif (loginContainer) {\r\n\t\t\t\t\tloginContainer.classList.remove('doboard_task_widget-hidden');\r\n\t\t\t\t\tif (submitButton) {\r\n\t\t\t\t\t\tsubmitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Response error');\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tthrow error;\r\n\t\t});\r\n}\r\n\r\nfunction userUpdate(projectToken, accountId) {\r\n\tconst sessionId = localStorage.getItem('spotfix_session_id');\r\n\tconst userId = localStorage.getItem('spotfix_user_id');\r\n\tconst timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\r\n\r\n\treturn userUpdateDoboard(projectToken, accountId, sessionId, userId, timezone);\r\n}\r\n\r\nfunction spotFixSplitUrl(url) {\r\n\ttry {\r\n\t\tif (!url || url.trim() === '') {\r\n\t\t\treturn '';\r\n\t\t}\r\n\t\tconst u = new URL(url);\r\n\t\tconst domain = u.host;\r\n\r\n\t\tconst segments = u.pathname.split('/').filter(Boolean);\r\n\r\n\t\tif (segments.length === 0) {\r\n\t\t\treturn domain;\r\n\t\t}\r\n\r\n\t\tconst reversed = segments.reverse();\r\n\t\treversed.push(domain);\r\n\t\treturn reversed.join(' / ');\r\n\t} catch (error) {\r\n\t\treturn '';\r\n\t}\r\n\r\n}\r\n\r\nfunction setToggleStatus(rootElement){\r\n\tconst clickHandler = () => {\r\n\t\tconst timer = setTimeout(() => {\r\n\t\t\tlocalStorage.setItem('spotfix_widget_is_closed', '1');\r\n\t\t\trootElement.hide();\r\n\t\t\tclearTimeout(timer);\r\n\t\t}, 300);\r\n\t};\r\n\tconst toggle = document.getElementById('widget_visibility');\r\n\tif(toggle) {\r\n\t\ttoggle.checked = true;\r\n\t\ttoggle.addEventListener('click', clickHandler);\r\n\t}\r\n}\r\n\r\nfunction checkLogInOutButtonsVisible (){\r\n\tif(!localStorage.getItem('spotfix_session_id')) {\r\n\t\tconst el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');\r\n\t\tif(el) el.style.display = 'none';\r\n\r\n\t\tconst loginContainer = document.getElementById('doboard_task_widget-input-container-login')\r\n\t\tif(loginContainer) {\r\n\t\t\tloginContainer.classList.remove('doboard_task_widget-hidden');\r\n\t\t}\r\n\t\tclearUserMenuData();\r\n\t} else {\r\n\t\tconst el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');\r\n\t\tif(el) el.style.display = 'block';\r\n\t\tconst loginContainer = document.getElementById('doboard_task_widget-input-container-login')\r\n\t\tif(loginContainer) {\r\n\t\t\tloginContainer.classList.add('doboard_task_widget-hidden');\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Clear user menu data in menu\r\n */\r\nasync function clearUserMenuData() {\r\n\tconst userNameElement = document.querySelector('.doboard_task_widget-user_menu-header-user-name');\r\n\tconst emailElement = document.querySelector('.doboard_task_widget-user_menu-header-email');\r\n\tconst avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');\r\n\r\n\tif (userNameElement) {\r\n\t\tuserNameElement.innerText = 'Guest';\r\n\t}\r\n\tif (emailElement) {\r\n\t\temailElement.innerText = '';\r\n\t}\r\n\tif (avatarElement) {\r\n\t\tavatarElement.src = SpotFixSVGLoader.getAsDataURI('iconAvatar');\r\n\t}\r\n}\r\n\r\nfunction changeSize(container){\r\n\tif(container && +localStorage.getItem('maximize')){\r\n\t\tcontainer.classList.add('doboard_task_widget-container-maximize');\r\n\t} else if(container) {\r\n\t\tcontainer.classList.remove('doboard_task_widget-container-maximize');\r\n\t}\r\n}\r\n\n/**\r\n * Widget class to create a task widget\r\n */\r\nclass CleanTalkWidgetDoboard {\r\n selectedText = '';\r\n selectedData = {};\r\n widgetElement = null;\r\n params = {};\r\n currentActiveTaskId = 0;\r\n savedIssuesQuantityOnPage = 0;\r\n savedIssuesQuantityAll = 0;\r\n allTasksData = {};\r\n srcVariables = {};\r\n\r\n /**\r\n * Constructor\r\n */\r\n constructor(selectedData, type) {\r\n this.selectedData = selectedData || '';\r\n this.selectedText = selectedData?.selectedText || '';\r\n this.srcVariables = {\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n iconEllipsesMore: SpotFixSVGLoader.getAsDataURI('iconEllipsesMore'),\r\n iconPlus: SpotFixSVGLoader.getAsDataURI('iconPlus'),\r\n iconMaximize: SpotFixSVGLoader.getAsDataURI('iconMaximize'),\r\n chevronBack: SpotFixSVGLoader.getAsDataURI('chevronBack'),\r\n buttonPaperClip: SpotFixSVGLoader.getAsDataURI('buttonPaperClip'),\r\n buttonSendMessage: SpotFixSVGLoader.getAsDataURI('buttonSendMessage'),\r\n logoDoBoardGreen: SpotFixSVGLoader.getAsDataURI('logoDoBoardGreen'),\r\n logoDoBoardWrap: SpotFixSVGLoader.getAsDataURI('logoDoBoardWrap'),\r\n iconSpotWidgetWrapPencil: SpotFixSVGLoader.getAsDataURI('iconSpotWidgetWrapPencil'),\r\n iconMarker: SpotFixSVGLoader.getAsDataURI('iconMarker'),\r\n iconSpotPublic: SpotFixSVGLoader.getAsDataURI('iconSpotPublic'),\r\n iconSpotPrivate: SpotFixSVGLoader.getAsDataURI('iconSpotPrivate'),\r\n iconLinkChain: SpotFixSVGLoader.getAsDataURI('iconLinkChain'),\r\n };\r\n this.fileUploader = new FileUploader(this.escapeHtml);\r\n this.init(type);\r\n }\r\n\r\n /**\r\n * Initialize the widget\r\n */\r\n async init(type) {\r\n this.params = this.getParams();\r\n\r\n // Check if email_confirmation_token is in URL\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const emailToken = urlParams.get('email_confirmation_token');\r\n if (emailToken) {\r\n try {\r\n // Confirm email and create task\r\n const createdTask = await confirmUserEmail(emailToken, this.params);\r\n this.allTasksData = await getAllTasks(this.params);\r\n // Open task interface\r\n this.currentActiveTaskId = createdTask.taskId;\r\n type = 'concrete_issue';\r\n storageSetWidgetIsClosed(false);\r\n // Clear email_confirmation_token from URL\r\n urlParams.delete('email_confirmation_token');\r\n const newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');\r\n window.history.replaceState({}, document.title, newUrl);\r\n } catch (err) {\r\n this.registrationShowMessage('Error confirming email: ' + err.message, 'error');\r\n }\r\n } else {\r\n // Load all tasks\r\n const isWidgetClosed = localStorage.getItem('spotfix_widget_is_closed');\r\n if((isWidgetClosed && !this.selectedText) || !isWidgetClosed){\r\n this.allTasksData = await getAllTasks(this.params);\r\n }\r\n }\r\n\r\n // Check if any task has updates\r\n let taskHasSiteOwnerUpdate;\r\n\r\n if (storageTasksHasUnreadUpdates()) {\r\n taskHasSiteOwnerUpdate = true;\r\n } else {\r\n if (type === 'wrap_review') {\r\n taskHasSiteOwnerUpdate = await checkIfTasksHasSiteOwnerUpdates(\r\n this.allTasksData,\r\n this.params\r\n );\r\n }\r\n }\r\n storageSaveTasksUpdateData(this.allTasksData);\r\n //check to hide on first run\r\n if (!storageWidgetCloseIsSet()) {\r\n storageSetWidgetIsClosed(true);\r\n }\r\n //check to show if any task has site owner updates\r\n if (taskHasSiteOwnerUpdate) {\r\n\r\n storageSetWidgetIsClosed(false);\r\n }\r\n this.widgetElement = await this.createWidgetElement(type);\r\n this.bindWidgetInputsInteractive();\r\n }\r\n\r\n getParams() {\r\n const script = document.querySelector(`script[src*=\"doboard-widget-bundle.\"]`);\r\n if ( ! script || ! script.src ) {\r\n throw new Error('Script not provided');\r\n }\r\n\r\n const url = new URL(script.src);\r\n let params = Object.fromEntries(url.searchParams.entries());\r\n if ( ! params ) {\r\n throw new Error('Script params not provided');\r\n }\r\n if ( ! params.projectToken || ! params.accountId || ! params.projectId ) {\r\n throw new Error('Necessary script params not provided');\r\n\r\n }\r\n if (params.accountId) {\r\n localStorage.setItem('spotfix_company_id', params.accountId);\r\n }\r\n if (params.projectToken) {\r\n localStorage.setItem('spotfix_project_token', params.projectToken);\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Binding events to create a task\r\n */\r\n bindCreateTaskEvents() {\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\r\n if (submitButton) {\r\n submitButton.addEventListener('click', async () => {\r\n // Check required fields: Report about and Description\r\n const taskTitleElement = document.getElementById('doboard_task_widget-title');\r\n const taskTitle = taskTitleElement.value;\r\n if ( ! taskTitle ) {\r\n taskTitleElement.style.borderColor = 'red';\r\n taskTitleElement.focus();\r\n taskTitleElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n const taskDescriptionElement = document.getElementById('doboard_task_widget-description')\r\n const taskDescription = taskDescriptionElement.value;\r\n if ( ! taskDescription ) {\r\n taskDescriptionElement.style.borderColor = 'red';\r\n taskDescriptionElement.focus();\r\n taskDescriptionElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n // If login section is open, check required fields: Nickname, Email\r\n let userName = '';\r\n let userEmail = '';\r\n let userPassword = '';\r\n const loginSectionElement = document.querySelector('.doboard_task_widget-login');\r\n const sessionIdExists = !!localStorage.getItem('spotfix_session_id');\r\n\r\n if ( !sessionIdExists && loginSectionElement && loginSectionElement.classList.contains('active') ) {\r\n const userEmailElement = document.getElementById('doboard_task_widget-user_email');\r\n const userNameElement = document.getElementById('doboard_task_widget-user_name');\r\n const userPasswordElement = document.getElementById('doboard_task_widget-user_password');\r\n\r\n userEmail = userEmailElement.value;\r\n if ( ! userEmail ) {\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n userEmailElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n // This is the registration request\r\n if ( userEmailElement && userNameElement ) {\r\n userName = userNameElement.value;\r\n if ( ! userName ) {\r\n userNameElement.style.borderColor = 'red';\r\n userNameElement.focus();\r\n userNameElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n }\r\n\r\n // This is the login request\r\n if ( userEmailElement && userPasswordElement && ! userNameElement ) {\r\n userPassword = userPasswordElement.value;\r\n if ( ! userPassword ) {\r\n userPasswordElement.style.borderColor = 'red';\r\n userPasswordElement.focus();\r\n userPasswordElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n }\r\n\r\n }\r\n\r\n // If it is the login request\r\n const userEmailElement = document.getElementById('doboard_task_widget-user_email');\r\n userEmail = userEmailElement.value;\r\n\r\n // Make the submit button disable with spinner\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n submitButton.disabled = true;\r\n submitButton.innerText = ksesFilter('Creating spot...');\r\n\r\n let taskDetails = {\r\n taskTitle: taskTitle,\r\n taskDescription: taskDescription,\r\n //typeSend: typeSend,\r\n selectedData: this.selectedData,\r\n projectToken: this.params.projectToken,\r\n projectId: this.params.projectId,\r\n accountId: this.params.accountId,\r\n taskMeta: JSON.stringify(this.selectedData ? this.selectedData : { pageURL: window.location.href }),\r\n };\r\n\r\n if ( userEmail ) {\r\n taskDetails.userEmail = userEmail\r\n }\r\n if ( userName ) {\r\n taskDetails.userName = userName\r\n }\r\n if ( userPassword ) {\r\n taskDetails.userPassword = userPassword\r\n }\r\n\r\n // Save pending task in LS\r\n localStorage.setItem('spotfix_pending_task', JSON.stringify({\r\n ...this.selectedData,\r\n description: taskDescription\r\n }));\r\n\r\n let submitTaskResult;\r\n try {\r\n submitTaskResult = await this.submitTask(taskDetails);\r\n } catch (error) {\r\n this.registrationShowMessage(error.message);\r\n return;\r\n }\r\n\r\n // Return the submit button normal state\r\n submitButton.disabled = false;\r\n submitButton.style.cursor = 'pointer';\r\n\r\n if ( submitTaskResult.needToLogin ) {\r\n // @ToDo Do not know what to de here: throw an error or pass log message?\r\n return;\r\n }\r\n\r\n if ( submitTaskResult.isPublic !== undefined ) {\r\n this.selectedData.isPublic = submitTaskResult.isPublic\r\n }\r\n\r\n // refersh tasks list after creation\r\n this.allTasksData = await getAllTasks(this.params);\r\n // save updates\r\n storageSaveTasksUpdateData(this.allTasksData);\r\n\r\n this.selectedData = {};\r\n await this.createWidgetElement('all_issues');\r\n storageSetWidgetIsClosed(false);\r\n hideContainersSpinner(false);\r\n });\r\n }\r\n }\r\n\r\n\r\n resetLoginForm() {\r\n const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');\r\n const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\r\n if (loginContainer) {\r\n loginContainer.classList.add('doboard_task_widget-hidden');\r\n }\r\n if (phantomContainer) {\r\n phantomContainer.classList.remove('doboard_task_widget-hidden');\r\n }\r\n if (submitButton) {\r\n submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');\r\n }\r\n }\r\n bindShowLoginFormEvents() {\r\n const showLoginButton = document.getElementById('doboard_task_widget-show_login_form');\r\n const showPhantomLoginButton = document.getElementById('doboard_task_widget-on_phantom_login_page');\r\n const forgotPasswordButton = document.getElementById('doboard_task_widget-forgot_password');\r\n const forgotPasswordButtonBlack = document.getElementById('doboard_task_widget-forgot_password-black');\r\n const loginButton = document.getElementById('doboard_task_widget-login_button');\r\n const restorePasswordButton = document.getElementById('doboard_task_widget-restore_password_button');\r\n\r\n if (showLoginButton) {\r\n showLoginButton.addEventListener('click', async () => {\r\n const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');\r\n const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n if (loginContainer) {\r\n loginContainer.classList.toggle('doboard_task_widget-hidden');\r\n if (submitButton) {\r\n if (loginContainer.classList.contains('doboard_task_widget-hidden')) {\r\n submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');\r\n } else {\r\n submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');\r\n }\r\n }\r\n }\r\n if (phantomContainer) {\r\n phantomContainer.classList.toggle('doboard_task_widget-hidden');\r\n }\r\n })\r\n }\r\n if (showPhantomLoginButton) {\r\n showPhantomLoginButton.addEventListener('click', async () => {\r\n const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');\r\n const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n if (loginContainer) {\r\n loginContainer.classList.toggle('doboard_task_widget-hidden');\r\n if (submitButton) {\r\n if (loginContainer.classList.contains('doboard_task_widget-hidden')) {\r\n submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');\r\n } else {\r\n submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');\r\n }\r\n }\r\n }\r\n if (phantomContainer) {\r\n phantomContainer.classList.toggle('doboard_task_widget-hidden');\r\n }\r\n })\r\n }\r\n if (forgotPasswordButton) {\r\n forgotPasswordButton.addEventListener('click', async () => {\r\n const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');\r\n const loginContainer = document.getElementById('doboard_task_widget-input-container-login');\r\n \r\n if (forgotPasswordForm) {\r\n forgotPasswordForm.classList.remove('doboard_task_widget-hidden');\r\n }\r\n if (loginContainer) {\r\n loginContainer.classList.add('doboard_task_widget-hidden');\r\n }\r\n })\r\n\r\n forgotPasswordButtonBlack.addEventListener('click', async () => {\r\n const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');\r\n const loginContainer = document.getElementById('doboard_task_widget-input-container-login');\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n\r\n if (forgotPasswordForm) {\r\n forgotPasswordForm.classList.add('doboard_task_widget-hidden');\r\n }\r\n if (loginContainer) {\r\n loginContainer.classList.remove('doboard_task_widget-hidden');\r\n if (submitButton) {\r\n submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');\r\n }\r\n }\r\n })\r\n }\r\n const forgotPasswordButtonMenu = document.querySelector('.doboard_task_widget-input-container-login-menu #doboard_task_widget-forgot_password');\r\n if (forgotPasswordButtonMenu) {\r\n forgotPasswordButtonMenu.addEventListener('click', async () => {\r\n const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');\r\n const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');\r\n \r\n if (forgotPasswordForm) {\r\n forgotPasswordForm.classList.remove('doboard_task_widget-hidden');\r\n }\r\n if (loginContainer) {\r\n loginContainer.classList.add('doboard_task_widget-hidden');\r\n }\r\n });\r\n }\r\n const forgotPasswordButtonBlackMenu = document.querySelector('.doboard_task_widget-input-container-login-menu ~ #doboard_task_widget-container-login-forgot-password-form #doboard_task_widget-forgot_password-black');\r\n if (forgotPasswordButtonBlackMenu) {\r\n forgotPasswordButtonBlackMenu.addEventListener('click', async () => {\r\n const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');\r\n const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');\r\n\r\n if (forgotPasswordForm) {\r\n forgotPasswordForm.classList.add('doboard_task_widget-hidden');\r\n }\r\n if (loginContainer) {\r\n loginContainer.classList.remove('doboard_task_widget-hidden');\r\n }\r\n });\r\n }\r\n if (loginButton) {\r\n loginButton.addEventListener('click', async () => {\r\n const userEmailElement = document.getElementById('doboard_task_widget-login_email');\r\n const userPasswordElement = document.getElementById('doboard_task_widget-login_password');\r\n document.querySelector('.doboard_task_widget-login-is-invalid').classList.add('doboard_task_widget-hidden');\r\n\r\n const userEmail = userEmailElement.value.trim();\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!userEmail) {\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n userEmailElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n } else if (!emailRegex.test(userEmail)) {\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n userEmailElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n const userPassword = userPasswordElement.value;\r\n if (!userPassword) {\r\n userPasswordElement.style.borderColor = 'red';\r\n userPasswordElement.focus();\r\n userPasswordElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n } else if (userPassword.length < 6) {\r\n userPasswordElement.style.borderColor = 'red';\r\n userPasswordElement.focus();\r\n userPasswordElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n await loginUser({\r\n userEmail: userEmail,\r\n userPassword: userPassword\r\n })(this.registrationShowMessage);\r\n this.setUserMenuData();\r\n\r\n const submitButton = document.getElementById('doboard_task_widget-submit_button');\r\n if (submitButton) {\r\n submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');\r\n }\r\n\r\n } catch (error) {\r\n document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');\r\n }\r\n const sessionIdExists = !!localStorage.getItem('spotfix_session_id');\r\n const email = localStorage.getItem('spotfix_email');\r\n if (sessionIdExists && email && !email.includes('spotfix_')) {\r\n const loginEl= document.querySelector('.doboard_task_widget-login');\r\n loginEl?.classList?.add('doboard_task_widget-hidden');\r\n } else {\r\n document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');\r\n }\r\n })\r\n }\r\n const passwordToggle = document.getElementById('doboard_task_widget-password-toggle');\r\n const passwordInput = document.getElementById('doboard_task_widget-login_password');\r\n \r\n if (passwordToggle && passwordInput) {\r\n passwordToggle.addEventListener('click', function() {\r\n const isPassword = passwordInput.type === 'password';\r\n passwordInput.type = isPassword ? 'text' : 'password';\r\n this.classList.toggle('doboard_task_widget-bottom-eye-off-icon');\r\n this.classList.toggle('doboard_task_widget-bottom-eye-icon');\r\n });\r\n }\r\n if (restorePasswordButton) {\r\n restorePasswordButton.addEventListener('click', async () => {\r\n const userEmailElement = document.getElementById('doboard_task_widget-forgot_password_email');\r\n const userEmail = userEmailElement.value.trim();\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!userEmail) {\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n userEmailElement.addEventListener('input', function() {\r\n this.style.borderColor = '';\r\n });\r\n return;\r\n } else if (!emailRegex.test(userEmail)) {\r\n\r\n userEmailElement.style.borderColor = 'red';\r\n userEmailElement.focus();\r\n\r\n return;\r\n }\r\n\r\n try {\r\n await forgotPassword(userEmail)(this.registrationShowMessage);\r\n } catch (error) {\r\n this.registrationShowMessage(error.message, 'error');\r\n }\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * Create widget element\r\n * @return {HTMLElement} widget element\r\n */\r\n async createWidgetElement(type, showOnlyCurrentPage = false) {\r\n const widgetContainer = document.querySelector('.doboard_task_widget') ? document.querySelector('.doboard_task_widget') : document.createElement('div');\r\n widgetContainer.className = 'doboard_task_widget';\r\n widgetContainer.innerHTML = ksesFilter('');\r\n widgetContainer.removeAttribute('style');\r\n\r\n let templateName = '';\r\n let tasksFullDetails;\r\n\r\n let templateVariables = {};\r\n\r\n const config = window.SpotfixWidgetConfig;\r\n\r\n switch (type) {\r\n case 'create_issue':\r\n templateName = 'create_issue';\r\n this.type_name = templateName;\r\n templateVariables = {\r\n selectedText: this.selectedText,\r\n currentDomain: document.location.hostname || '',\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n iconMaximize: SpotFixSVGLoader.getAsDataURI('iconMaximize'),\r\n iconEllipsesMore: SpotFixSVGLoader.getAsDataURI('iconEllipsesMore'),\r\n ...this.srcVariables\r\n };\r\n storageGetUserIsDefined() && storageSetWidgetIsClosed(false);\r\n break;\r\n case 'wrap':\r\n if (storageGetWidgetIsClosed()) {\r\n return;\r\n }\r\n\r\n templateName = 'wrap';\r\n templateVariables = {position: !Number.isNaN(Number(config?.verticalPosition))\r\n ? `${Number(config?.verticalPosition)}vh` : '0vh', ...this.srcVariables};\r\n break;\r\n case 'wrap_review':\r\n templateName = 'wrap_review';\r\n templateVariables = {position: !Number.isNaN(Number(config?.verticalPosition))\r\n ? `${Number(config?.verticalPosition)}vh` : '0vh', ...this.srcVariables};\r\n break;\r\n case 'all_issues':\r\n templateName = 'all_issues';\r\n this.type_name = templateName;\r\n templateVariables = {...this.srcVariables};\r\n break;\r\n case 'user_menu':\r\n templateName = 'user_menu';\r\n const version = localStorage.getItem('spotfix_app_version') || SPOTFIX_VERSION;\r\n templateVariables = {\r\n spotfixVersion: version ? 'Spotfix version ' + version + '.' : '',\r\n avatar: SpotFixSVGLoader.getAsDataURI('iconAvatar'),\r\n iconEye: SpotFixSVGLoader.getAsDataURI('iconEye'),\r\n iconDoor: SpotFixSVGLoader.getAsDataURI('iconDoor'),\r\n chevronBackDark: SpotFixSVGLoader.getAsDataURI('chevronBackDark'),\r\n buttonCloseScreen: SpotFixSVGLoader.getAsDataURI('buttonCloseScreen'),\r\n userName: 'Guest',\r\n email: localStorage.getItem('spotfix_email') || '',\r\n ...this.srcVariables};\r\n break;\r\n case 'concrete_issue':\r\n templateName = 'concrete_issue';\r\n this.type_name = templateName;\r\n // Update the number of tasks\r\n this.savedIssuesQuantityAll = Array.isArray(this.allTasksData) ? this.allTasksData.length : 0;\r\n // Calculate the number of issues on the current page\r\n this.savedIssuesQuantityOnPage = Array.isArray(this.allTasksData)\r\n ? this.allTasksData.filter(task => {\r\n try {\r\n const meta = task.taskMeta ? JSON.parse(task.taskMeta) : {};\r\n return meta.pageURL === window.location.href;\r\n } catch (e) { return false; }\r\n }).length\r\n : 0;\r\n\r\n templateVariables = {\r\n issueTitle: '...',\r\n issueComments: [],\r\n issuesCounter: getIssuesCounterString(this.savedIssuesQuantityOnPage, this.savedIssuesQuantityAll),\r\n ...this.srcVariables,\r\n };\r\n break;\r\n default:\r\n break;\r\n }\r\n widgetContainer.innerHTML = this.loadTemplate(templateName, templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n\r\n // remove highlights before any screen called\r\n spotFixRemoveHighlights();\r\n const container = document.querySelector('.doboard_task_widget-container');\r\n switch (type) {\r\n case 'create_issue':\r\n\r\n if(container && +localStorage.getItem('maximize')){\r\n container.classList.add('doboard_task_widget-container-maximize');\r\n } else if(container) {\r\n container.classList.remove('doboard_task_widget-container-maximize');\r\n }\r\n // highlight selected item during task creation\r\n const selection = window.getSelection();\r\n const sessionIdExists = !!localStorage.getItem('spotfix_session_id');\r\n const email = localStorage.getItem('spotfix_email');\r\n\r\n if (sessionIdExists && email && !email.includes('spotfix_')) {\r\n document.querySelector('.doboard_task_widget-login').classList.add('hidden');\r\n }\r\n if (\r\n selection.type === 'Range'\r\n ) {\r\n const selectedData = spotFixGetSelectedData(selection);\r\n spotFixScrollToNodePath(selectedData.nodePath);\r\n this.positionWidgetContainer();\r\n }\r\n // bind creation events\r\n this.bindCreateTaskEvents();\r\n this.bindShowLoginFormEvents();\r\n break;\r\n case 'wrap':\r\n await this.getTaskCount();\r\n document.querySelector('.doboard_task_widget-wrap').addEventListener('click', (e) => {\r\n const widgetElementClasses = e.currentTarget.classList;\r\n if (widgetElementClasses && !widgetElementClasses.contains('hidden')) {\r\n this.createWidgetElement('all_issues');\r\n }\r\n });\r\n hideContainersSpinner(false);\r\n break;\r\n case 'wrap_review':\r\n document.querySelector('#doboard_task_widget_button').addEventListener('click', (e) => {\r\n spotFixOpenWidget(this.selectedData, 'create_issue');\r\n });\r\n break;\r\n case 'all_issues':\r\n changeSize(container);\r\n\r\n spotFixRemoveHighlights();\r\n let issuesQuantityOnPage = 0;\r\n if (!this.allTasksData?.length) {\r\n this.allTasksData = await getAllTasks(this.params);\r\n }\r\n const tasks = this.allTasksData;\r\n tasksFullDetails = await getTasksFullDetails(this.params, tasks, this.currentActiveTaskId);\r\n let spotsToBeHighlighted = [];\r\n if (tasks.length > 0) {\r\n const currentURL = window.location.href;\r\n const sortedTasks = tasks.sort((a, b) => {\r\n const aIsHere = JSON.parse(a.taskMeta).pageURL === currentURL ? 1 : 0;\r\n const bIsHere = JSON.parse(b.taskMeta).pageURL === currentURL ? 1 : 0;\r\n return bIsHere - aIsHere;\r\n });\r\n\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML = '';\r\n\r\n for (let i = 0; i < sortedTasks.length; i++) {\r\n const elTask = sortedTasks[i];\r\n\r\n // Data from api\r\n const taskId = elTask.taskId;\r\n const taskTitle = elTask.taskTitle;\r\n const taskMetaString = elTask.taskMeta;\r\n let taskData = null;\r\n if (taskMetaString) {\r\n try {\r\n taskData = JSON.parse(taskMetaString);\r\n taskData.isFixed = elTask.taskStatus === 'DONE';\r\n taskData.taskId = elTask.taskId;\r\n } catch (error) {\r\n taskData = null;\r\n }\r\n }\r\n const currentPageURL = taskData ? taskData.pageURL : '';\r\n const taskNodePath = taskData ? taskData.nodePath : '';\r\n\r\n // Define publicity details\r\n let taskPublicStatusImgSrc = '';\r\n let taskPublicStatusHint = 'Task publicity is unknown'\r\n if (taskData && taskData.isPublic !== undefined) {\r\n if (taskData.isPublic) {\r\n taskPublicStatusImgSrc = this.srcVariables.iconSpotPublic;\r\n taskPublicStatusHint = 'The task is public';\r\n } else {\r\n taskPublicStatusImgSrc = this.srcVariables.iconSpotPrivate;\r\n taskPublicStatusHint = 'The task is private and visible only for registered DoBoard users';\r\n }\r\n }\r\n\r\n if(currentPageURL === window.location.href){\r\n issuesQuantityOnPage++;\r\n }\r\n\r\n if (!showOnlyCurrentPage || currentPageURL === window.location.href) {\r\n\r\n const taskFullDetails = getTaskFullDetails(tasksFullDetails, taskId)\r\n\r\n const avatarData = getAvatarData(taskFullDetails);\r\n const listIssuesTemplateVariables = {\r\n taskTitle: taskTitle || '',\r\n taskAuthorAvatarImgSrc: taskFullDetails.taskAuthorAvatarImgSrc,\r\n taskAuthorName: taskFullDetails.taskAuthorName,\r\n taskPublicStatusImgSrc: taskPublicStatusImgSrc,\r\n taskPublicStatusHint: taskPublicStatusHint,\r\n taskLastMessage: ksesFilter(taskFullDetails.lastMessageText),\r\n taskPageUrl: currentPageURL,\r\n iconLinkChain: this.srcVariables.iconLinkChain,\r\n taskFormattedPageUrl: spotFixSplitUrl(currentPageURL),\r\n taskLastUpdate: taskFullDetails.lastMessageTime,\r\n nodePath: this.sanitizeNodePath(taskNodePath),\r\n taskId: taskId,\r\n avatarCSSClass: avatarData.avatarCSSClass,\r\n avatarStyle: avatarData.avatarStyle,\r\n taskAuthorInitials: avatarData.taskAuthorInitials,\r\n initialsClass: avatarData.initialsClass,\r\n classUnread: '',\r\n elementBgCSSClass: elTask.taskStatus !== 'DONE' ? '' : 'doboard_task_widget-task_row-green',\r\n statusFixedHtml: elTask.taskStatus !== 'DONE' ? '' : this.loadTemplate('fixedHtml'),\r\n };\r\n\r\n const taskOwnerReplyIsUnread = storageProvidedTaskHasUnreadUpdates(taskFullDetails.taskId);\r\n if (taskOwnerReplyIsUnread) {\r\n listIssuesTemplateVariables.classUnread = 'unread';\r\n }\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML += this.loadTemplate('list_issues', listIssuesTemplateVariables);\r\n\r\n if ( this.isSpotHaveToBeHighlighted(taskData) ) {\r\n spotsToBeHighlighted.push(taskData);\r\n }\r\n }\r\n }\r\n this.savedIssuesQuantityOnPage = issuesQuantityOnPage;\r\n this.savedIssuesQuantityAll = tasks.length;\r\n spotFixHighlightElements(spotsToBeHighlighted, this);\r\n document.querySelector('.doboard_task_widget-header span').innerHTML += ksesFilter(' ' + getIssuesCounterString(this.savedIssuesQuantityOnPage, this.savedIssuesQuantityAll));\r\n }\r\n\r\n if (tasks.length === 0) {\r\n document.querySelector(\".doboard_task_widget-all_issues-container\").innerHTML = ksesFilter('The issues list is empty
');\r\n }\r\n\r\n // Bind the click event to the task elements for scrolling to the selected text and Go to concrete issue interface by click issue-item row\r\n this.bindIssuesClick();\r\n hideContainersSpinner(false);\r\n break;\r\n case 'user_menu':\r\n\r\n setToggleStatus(this);\r\n checkLogInOutButtonsVisible();\r\n\r\n const user = await getUserDetails(this.params);\r\n const gitHubAppVersion = await getReleaseVersion();\r\n let spotfixVersion = '';\r\n const version = localStorage.getItem('spotfix_app_version') || gitHubAppVersion || SPOTFIX_VERSION;\r\n spotfixVersion = version ? `Spotfix version ${version}.` : '';\r\n\r\n templateVariables.spotfixVersion = spotfixVersion || '';\r\n\r\n if(user){\r\n templateVariables.userName = user.name || 'Guest';\r\n templateVariables.email = user.email || localStorage.getItem('spotfix_email') || '';\r\n if(user?.avatar?.s) templateVariables.avatar = user?.avatar?.s;\r\n }\r\n\r\n widgetContainer.innerHTML = this.loadTemplate('user_menu', templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n setToggleStatus(this);\r\n checkLogInOutButtonsVisible();\r\n this.bindShowLoginFormEvents();\r\n this.bindWidgetInputsInteractive();\r\n\r\n break;\r\n case 'concrete_issue':\r\n changeSize(container);\r\n tasksFullDetails = await getTasksFullDetails(this.params, this.allTasksData, this.currentActiveTaskId);\r\n const taskDetails = await getTaskFullDetails(tasksFullDetails, this.currentActiveTaskId);\r\n // Update issue title in the interface\r\n const issueTitleElement = document.querySelector('.doboard_task_widget-issue-title');\r\n if (issueTitleElement) {\r\n issueTitleElement.innerText = ksesFilter(taskDetails.issueTitle);\r\n }\r\n\r\n templateVariables.issueTitle = taskDetails?.issueTitle;\r\n templateVariables.issueComments = taskDetails?.issueComments;\r\n\r\n\r\n // Highlight the task's selected text\r\n let nodePath = null;\r\n const currentTaskData = this.allTasksData.find((element) => String(element.taskId) === String(taskDetails.taskId));\r\n let meta = null;\r\n\r\n if (currentTaskData && currentTaskData.taskMeta) {\r\n try {\r\n meta = JSON.parse(currentTaskData.taskMeta);\r\n nodePath = meta.nodePath || null;\r\n } catch (e) { nodePath = null; meta = null; }\r\n }\r\n\r\n templateVariables.taskPageUrl = meta.pageURL;\r\n const taskFormattedPageUrl = meta.pageURL.replace(window.location.origin, '');\r\n templateVariables.taskFormattedPageUrl = taskFormattedPageUrl.length < 2\r\n ? meta.pageURL.replace(window.location.protocol + '/', '') : taskFormattedPageUrl;\r\n templateVariables.contenerClasess = +localStorage.getItem('maximize')\r\n ? 'doboard_task_widget-container-maximize doboard_task_widget-container' : 'doboard_task_widget-container'\r\n widgetContainer.innerHTML = this.loadTemplate('concrete_issue', templateVariables);\r\n document.body.appendChild(widgetContainer);\r\n\r\n // remove old highlights before adding new ones\r\n spotFixRemoveHighlights();\r\n\r\n if (meta && nodePath) {\r\n // Pass the task meta object as an array\r\n spotFixHighlightElements([meta], this);\r\n if (typeof spotFixScrollToNodePath === 'function') {\r\n spotFixScrollToNodePath(nodePath);\r\n }\r\n }\r\n\r\n const issuesCommentsContainer = document.querySelector('.doboard_task_widget-concrete_issues-container');\r\n let dayMessagesData = [];\r\n const initIssuerID = localStorage.getItem('spotfix_user_id');\r\n let userIsIssuer = false;\r\n if ( taskDetails.issueComments.length > 0 ) {\r\n storageRemoveUnreadUpdateForTaskID(taskDetails.taskId);\r\n issuesCommentsContainer.innerHTML = ksesFilter('');\r\n for (const comment of taskDetails.issueComments) {\r\n userIsIssuer = Number(initIssuerID) === Number(comment.commentUserId);\r\n const avatarData = getAvatarData({\r\n taskAuthorAvatarImgSrc: comment.commentAuthorAvatarSrc,\r\n taskAuthorName: comment.commentAuthorName,\r\n });\r\n const commentData = {\r\n commentAuthorName: comment.commentAuthorName,\r\n commentBody: comment.commentBody,\r\n commentDate: comment.commentDate,\r\n commentTime: comment.commentTime,\r\n issueTitle: templateVariables.issueTitle,\r\n avatarCSSClass: avatarData.avatarCSSClass,\r\n avatarStyle: avatarData.avatarStyle,\r\n taskAuthorInitials: avatarData.taskAuthorInitials,\r\n initialsClass: avatarData.initialsClass,\r\n issueMessageClassOwner: userIsIssuer ? 'owner' : 'guest',\r\n };\r\n if (dayMessagesData[comment.commentDate] === undefined) {\r\n dayMessagesData[comment.commentDate] = [];\r\n dayMessagesData[comment.commentDate].push(commentData);\r\n } else {\r\n dayMessagesData[comment.commentDate].push(commentData);\r\n }\r\n }\r\n let daysWrapperHTML = '';\r\n\r\n for (const day in dayMessagesData) {\r\n let currentDayMessages = dayMessagesData[day];\r\n let dayMessagesWrapperHTML = '';\r\n currentDayMessages.sort((a, b) => a.commentTime.localeCompare(b.commentTime));\r\n for (const messageId in currentDayMessages) {\r\n let currentMessageTemplateVariables = currentDayMessages[messageId];\r\n dayMessagesWrapperHTML += this.loadTemplate('concrete_issue_messages', currentMessageTemplateVariables);\r\n }\r\n daysWrapperHTML += this.loadTemplate('concrete_issue_day_content',\r\n {\r\n dayContentMonthDay: day,\r\n dayContentMessages: dayMessagesWrapperHTML,\r\n statusFixedHtml: tasksFullDetails?.taskStatus !== 'DONE' ? '' : this.loadTemplate('fixedTaskHtml')\r\n },\r\n );\r\n }\r\n issuesCommentsContainer.innerHTML = daysWrapperHTML;\r\n } else {\r\n issuesCommentsContainer.innerHTML = ksesFilter('No comments');\r\n }\r\n\r\n // textarea (new comment) behaviour\r\n const textarea = document.querySelector('.doboard_task_widget-send_message_input');\r\n if (textarea) {\r\n function handleTextareaChange() {\r\n const triggerChars = 40;\r\n\r\n if (this.value.length > triggerChars) {\r\n this.classList.add('high');\r\n } else {\r\n this.classList.remove('high');\r\n }\r\n }\r\n textarea.addEventListener('input', handleTextareaChange)\r\n textarea.addEventListener('change', handleTextareaChange)\r\n }\r\n\r\n // Hide spinner preloader\r\n hideContainersSpinner();\r\n\r\n // Scroll to the bottom comments\r\n setTimeout(() => {\r\n const contentContainer = document.querySelector('.doboard_task_widget-content');\r\n contentContainer.scrollTo({\r\n top: contentContainer.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }, 0);\r\n\r\n const sendButton = document.querySelector('.doboard_task_widget-send_message_button');\r\n if (sendButton) {\r\n this.fileUploader.init();\r\n let widgetClass = this;\r\n sendButton.addEventListener('click', async (e) => {\r\n e.preventDefault();\r\n\r\n const sendMessageContainer = sendButton.closest('.doboard_task_widget-send_message');\r\n const input = sendMessageContainer.querySelector('.doboard_task_widget-send_message_input');\r\n\r\n const commentText = input.value.trim();\r\n if (!commentText) return;\r\n\r\n // Add other fields handling here\r\n\r\n input.disabled = true;\r\n sendButton.disabled = true;\r\n\r\n let newCommentResponse = null;\r\n\r\n try {\r\n newCommentResponse = await addTaskComment(this.params, this.currentActiveTaskId, commentText);\r\n input.value = '';\r\n await this.createWidgetElement('concrete_issue');\r\n hideContainersSpinner(false);\r\n } catch (err) {\r\n alert('Error when adding a comment: ' + err.message);\r\n }\r\n\r\n if (widgetClass.fileUploader.hasFiles() && newCommentResponse !== null && newCommentResponse.hasOwnProperty('commentId')) {\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n const attachmentsSendResult = await widgetClass.fileUploader.sendAttachmentsForComment(widgetClass.params, sessionId, newCommentResponse.commentId);\r\n if (!attachmentsSendResult.success) {\r\n widgetClass.fileUploader.showError('Some files where no sent, see details in the console.');\r\n const toConsole = JSON.stringify(attachmentsSendResult);\r\n console.log(toConsole);\r\n }\r\n }\r\n\r\n input.disabled = false;\r\n sendButton.disabled = false;\r\n });\r\n }\r\n\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n\r\n const backToAllIssuesController = document.querySelector('.doboard_task_widget_return_to_all');\r\n const widgetClass = this;\r\n if ( backToAllIssuesController ) {\r\n backToAllIssuesController.addEventListener('click', function(e, self = widgetClass) {\r\n self.createWidgetElement('all_issues');\r\n });\r\n }\r\n\r\n const paperclipController = document.querySelector('.doboard_task_widget-send_message_paperclip');\r\n if ( paperclipController ) {\r\n this.fileUploader.bindPaperClipAction(paperclipController);\r\n }\r\n\r\n document.querySelector('.doboard_task_widget-close_btn')?.addEventListener('click', (e) => {\r\n this.hide();\r\n }) || '';\r\n\r\n document.querySelector('#openUserMenuButton')?.addEventListener('click', () => {\r\n this.createWidgetElement('user_menu')\r\n }) || '';\r\n\r\n document.querySelector('#doboard_task_widget-user_menu-logout_button')?.addEventListener('click', () => {\r\n logoutUserDoboard(this.params.projectToken);\r\n }) || '';\r\n\r\n document.getElementById('addNewTaskButton')?.addEventListener('click', () => {\r\n spotFixShowWidget();\r\n }) || '';\r\n\r\n document.getElementById('maximizeWidgetContainer')?.addEventListener('click', () => {\r\n const container = document.querySelector('.doboard_task_widget-container');\r\n\r\n if(+localStorage.getItem('maximize') && container.classList.contains('doboard_task_widget-container-maximize')){\r\n localStorage.setItem('maximize', '0');\r\n container.classList.remove('doboard_task_widget-container-maximize');\r\n } else {\r\n localStorage.setItem('maximize', '1');\r\n container.classList.add('doboard_task_widget-container-maximize');\r\n }\r\n }) || '';\r\n\r\n document.querySelector('#doboard_task_widget-user_menu-signlog_button')?.addEventListener('click', () => {\r\n spotFixShowWidget();\r\n }) || '';\r\n\r\n document.querySelector('#spotfix_back_button')?.addEventListener('click', () => {\r\n this.createWidgetElement(this.type_name)\r\n this.bindWidgetInputsInteractive();\r\n }) || '';\r\n\r\n return widgetContainer;\r\n }\r\n\r\n bindIssuesClick() {\r\n document.querySelectorAll('.issue-item').forEach(item => {\r\n item.addEventListener('click', async () => {\r\n let nodePath = null;\r\n try {\r\n nodePath = JSON.parse(item.getAttribute('data-node-path'));\r\n } catch (error) {\r\n nodePath = null;\r\n }\r\n if (nodePath) {\r\n spotFixScrollToNodePath(nodePath);\r\n }\r\n this.currentActiveTaskId = item.getAttribute('data-task-id');\r\n await this.showOneTask();\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Show one task\r\n *\r\n * @return {Promise}\r\n *\r\n */\r\n async showOneTask() {\r\n await this.createWidgetElement('concrete_issue');\r\n const taskHighlightData = this.getTaskHighlightData(this.currentActiveTaskId)\r\n\r\n if (taskHighlightData) {\r\n spotFixRemoveHighlights();\r\n spotFixHighlightElements([taskHighlightData], this)\r\n this.positionWidgetContainer();\r\n }\r\n\r\n hideContainersSpinner(false);\r\n }\r\n\r\n /**\r\n * Load the template\r\n *\r\n * @param templateName\r\n * @param variables\r\n * @return {string}\r\n * @ToDo have to refactor templates loaded method: need to be templates included into the bundle\r\n *\r\n */\r\n loadTemplate(templateName, variables = {}) {\r\n let template = SpotFixTemplatesLoader.getTemplateCode(templateName);\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n const placeholder = `{{${key}}}`;\r\n let replacement;\r\n\r\n // 1) For attributes we MUST use escapeHtml!\r\n // 2) Only for HTML inserts we must clean data by ksesFilter\r\n // Check if placeholder is used in an attribute context\r\n if (this.isPlaceholderInAttribute(template, placeholder)) {\r\n // For attributes, use escapeHtml to prevent XSS\r\n replacement = this.escapeHtml(String(value));\r\n } else {\r\n // For HTML content, use ksesFilter to sanitize HTML\r\n replacement = ksesFilter(String(value), {template: templateName, imgFilter: true});\r\n }\r\n\r\n template = template.replaceAll(placeholder, replacement);\r\n }\r\n\r\n return ksesFilter(template, {template: templateName});\r\n }\r\n\r\n /**\r\n * Check if a placeholder is used inside an HTML attribute\r\n * @param {string} template - The template string\r\n * @param {string} placeholder - The placeholder to check (e.g., \"{{key}}\")\r\n * @return {boolean} - True if placeholder is in an attribute context\r\n */\r\n isPlaceholderInAttribute(template, placeholder) {\r\n // Escape special regex characters in placeholder\r\n const escapedPlaceholder = placeholder.replace(/[{}]/g, '\\\\$&');\r\n\r\n // Pattern to match attribute=\"...\" or attribute='...' containing the placeholder\r\n // This regex looks for: word characters (attribute name) = \" or ' followed by content including the placeholder\r\n // Matches patterns like: src=\"{{key}}\", class=\"{{key}}\", style=\"{{key}}\", etc.\r\n const attributePattern = new RegExp(\r\n `[\\\\w-]+\\\\s*=\\\\s*[\"'][^\"']*${escapedPlaceholder}[^\"']*[\"']`,\r\n 'g'\r\n );\r\n\r\n // Check if placeholder appears in any attribute context\r\n // If it does, we'll use escapeHtml for all occurrences (safer approach)\r\n return attributePattern.test(template);\r\n }\r\n\r\n escapeHtml = (unsafe) => {\r\n return unsafe\r\n .replace(/&/g, \"&\")\r\n .replace(//g, \">\")\r\n .replace(/\"/g, \""\")\r\n .replace(/'/g, \"'\");\r\n };\r\n\r\n async getTaskCount() {\r\n if (!localStorage.getItem('spotfix_session_id')) {\r\n return {};\r\n }\r\n\r\n const projectToken = this.params.projectToken;\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\r\n const tasksCountLS = localStorage.getItem('spotfix_tasks_count');\r\n\r\n let tasksCount;\r\n\r\n if(tasksCountLS !== 0 && !tasksCountLS){\r\n await getTasksDoboard(projectToken, sessionId, this.params.accountId, this.params.projectId);\r\n const tasks = await spotfixIndexedDB.getAll(TABLE_TASKS);\r\n const filteredTasks = tasks.filter(task => {\r\n return task.taskMeta;\r\n });\r\n tasksCount = filteredTasks.length;\r\n } else tasksCount = tasksCountLS;\r\n\r\n const taskCountElement = document.getElementById('doboard_task_widget-task_count');\r\n if ( taskCountElement ) {\r\n taskCountElement.innerText = ksesFilter(tasksCount);\r\n taskCountElement.classList.remove('hidden');\r\n }\r\n }\r\n\r\n /**\r\n * Bind events to the widget\r\n */\r\n /*bindEvents() {\r\n this.submitButton.addEventListener('click', () => this.submitTask());\r\n }*/\r\n\r\n /**\r\n * Submit the task\r\n */\r\n async submitTask(taskDetails) {\r\n if (!localStorage.getItem('spotfix_session_id')) {\r\n await registerUser(taskDetails)(this.registrationShowMessage);\r\n if ( taskDetails.userPassword ) {\r\n await loginUser(taskDetails)(this.registrationShowMessage);\r\n checkLogInOutButtonsVisible();\r\n }\r\n }\r\n\r\n const sessionId = localStorage.getItem('spotfix_session_id');\r\n\r\n if ( ! sessionId ) {\r\n // @ToDo move this return in register block code\r\n return {needToLogin: true};\r\n }\r\n return await handleCreateTask(sessionId, taskDetails);\r\n }\r\n\r\n /**\r\n * Hide the widget\r\n */\r\n hide() {\r\n spotFixRemoveHighlights();\r\n this.createWidgetElement('wrap');\r\n\r\n }\r\n\r\n wrapElementWithSpotfixHighlight(element) {\r\n const newElement = element.cloneNode();\r\n const wrapper = document.createElement('span');\r\n wrapper.className = 'doboard_task_widget-text_selection image-highlight';\r\n\r\n element.insertAdjacentElement('beforebegin', wrapper);\r\n wrapper.appendChild(newElement);\r\n\r\n return wrapper;\r\n }\r\n\r\n /**\r\n * Get task spot data for highlighting.\r\n * @param {string|int} taskIdToSearch\r\n * @returns {object|null}\r\n */\r\n getTaskHighlightData(taskIdToSearch) {\r\n const currentTaskData = this.allTasksData.find((element) => element.taskId.toString() === taskIdToSearch.toString());\r\n if (currentTaskData && currentTaskData.taskMeta !== undefined) {\r\n let currentTaskSpotData = null;\r\n try {\r\n currentTaskSpotData = JSON.parse(currentTaskData.taskMeta);\r\n } catch (error) {\r\n currentTaskSpotData = null;\r\n }\r\n if (currentTaskSpotData !== null && typeof currentTaskSpotData === 'object') {\r\n return currentTaskSpotData;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n bindWidgetInputsInteractive() {\r\n // Customising placeholders\r\n const inputs = document.querySelectorAll('.doboard_task_widget-field');\r\n inputs.forEach(input => {\r\n if (input.value) {\r\n input.classList.add('has-value');\r\n }\r\n\r\n input.addEventListener('input', () => {\r\n if (input.value) {\r\n input.classList.add('has-value');\r\n } else {\r\n input.classList.remove('has-value');\r\n }\r\n });\r\n\r\n input.addEventListener('blur', () => {\r\n if (!input.value) {\r\n input.classList.remove('has-value');\r\n }\r\n });\r\n });\r\n\r\n // Customising accordion dropdown\r\n const accordionController = document.querySelector('.doboard_task_widget-login span');\r\n if ( accordionController ) {\r\n const context = this;\r\n accordionController.addEventListener('click', function() {\r\n this.closest('.doboard_task_widget-login').classList.toggle('active');\r\n // Scroll\r\n context.positionWidgetContainer();\r\n setTimeout(() => {\r\n const contentContainer = document.querySelector('.doboard_task_widget-content');\r\n contentContainer.scrollTo({\r\n top: contentContainer.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }, 0);\r\n });\r\n }\r\n\r\n window.addEventListener('scroll', this.handleScroll.bind(this));\r\n window.addEventListener('resize', this.handleResize.bind(this));\r\n }\r\n\r\n registrationShowMessage(messageText, type = 'error') {\r\n const titleSpan = document.getElementById('doboard_task_widget-error_message-header');\r\n const messageDiv = document.getElementById('doboard_task_widget-error_message');\r\n const messageWrap = document.querySelector('.doboard_task_widget-message-wrapper');\r\n\r\n if (typeof messageText === 'string' && messageDiv !== null && messageWrap !== null) {\r\n messageDiv.innerText = ksesFilter(messageText);\r\n messageWrap.classList.remove('hidden');\r\n messageDiv.classList.remove('doboard_task_widget-notice_message', 'doboard_task_widget-error_message');\r\n if (type === 'notice') {\r\n titleSpan.innerText = ksesFilter('');\r\n messageWrap.classList.add('doboard_task_widget-notice_message');\r\n messageDiv.style.color = '#2a5db0';\r\n } else {\r\n titleSpan.innerText = ksesFilter('Registration error');\r\n messageWrap.classList.add('doboard_task_widget-error_message');\r\n messageDiv.style.color = 'red';\r\n }\r\n }\r\n }\r\n\r\n positionWidgetContainer() {\r\n const selection = document.querySelector('.doboard_task_widget-text_selection');\r\n const widget = document.querySelector('.doboard_task_widget')\r\n const widgetCreateIssue = document.querySelector('.doboard_task_widget-content.doboard_task_widget-create_issue')\r\n const widgetConcreteIssue = document.querySelector('.doboard_task_widget-concrete_issues-container')\r\n if ( ! ( ( widgetCreateIssue || widgetConcreteIssue ) && selection ) ) {\r\n // Skip if the widget is closed or highlight not exist\r\n return;\r\n }\r\n\r\n const scrollY = window.scrollY;\r\n const viewportHeight = window.innerHeight;\r\n\r\n const selectionAbsoluteTop = selection.getBoundingClientRect().top + scrollY;\r\n\r\n const widgetHeight = widget.offsetHeight;\r\n\r\n let top;\r\n\r\n // Check selection position\r\n if (selectionAbsoluteTop - scrollY < 0) {\r\n // 1) The selection is above the viewport - stuck the widget on the top\r\n top = 10;\r\n } else if (selectionAbsoluteTop - scrollY > viewportHeight) {\r\n // 2) The selection is below the viewport - stuck the widget on the bottom\r\n top = viewportHeight - widgetHeight - 10;\r\n } else {\r\n // 3) The selection is on viewport - the widget aligned against the selection\r\n top = selectionAbsoluteTop - scrollY\r\n if ( selectionAbsoluteTop - scrollY > viewportHeight - widgetHeight ) {\r\n // 3.1) The selection is on viewport but is below than widget height - stuck the widget on the bottom\r\n top = viewportHeight - widgetHeight - 10;\r\n }\r\n }\r\n\r\n widget.style.top = `${top}px`;\r\n widget.style.bottom = 'auto';\r\n }\r\n\r\n handleScroll() {\r\n clearTimeout(this.scrollTimeout);\r\n this.scrollTimeout = setTimeout(() => {\r\n this.positionWidgetContainer();\r\n }, 10);\r\n }\r\n\r\n handleResize() {\r\n clearTimeout(this.resizeTimeout);\r\n this.resizeTimeout = setTimeout(() => {\r\n this.positionWidgetContainer();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Check nodePath, selectedData against page source and return is the provided nodePath is correct and can be highlighted\r\n * @param taskData\r\n * @return {boolean}\r\n */\r\n isSpotHaveToBeHighlighted(taskData) {\r\n return true;\r\n }\r\n\r\n sanitizeNodePath(nodePath) {\r\n let str = Array.isArray(nodePath) ? JSON.stringify(nodePath) : String(nodePath);\r\n // Allow only digits, commas, spaces, and square brackets\r\n if (/^[\\[\\]0-9,\\s]*$/.test(str)) {\r\n return str;\r\n }\r\n return '';\r\n}\r\n\r\n/**\r\n * Set user menu data with current user information\r\n */\r\nasync setUserMenuData() {\r\n const params = this.params;\r\n\r\n // Get user data\r\n let userData = null;\r\n if (localStorage.getItem('spotfix_session_id')) {\r\n try {\r\n userData = await getUserDetails(params);\r\n } catch (error) {\r\n console.error('Error fetching user details:', error);\r\n }\r\n }\r\n\r\n // Update user menu header\r\n const userNameElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*=\"font-size: 16px\"]');\r\n const emailElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*=\"font-size: 12px\"]');\r\n const avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');\r\n\r\n if (userNameElement) {\r\n if (userData && userData.name) {\r\n userNameElement.innerText = userData.name;\r\n } else {\r\n userNameElement.innerText = 'Guest';\r\n }\r\n }\r\n\r\n if (emailElement) {\r\n if (userData && userData.email) {\r\n emailElement.innerText = userData.email;\r\n } else {\r\n const email = localStorage.getItem('spotfix_email') || '';\r\n emailElement.innerText = email.includes('spotfix_') ? '' : email;\r\n }\r\n }\r\n\r\n if (avatarElement) {\r\n if (userData && userData.avatar && userData.avatar.s) {\r\n avatarElement.src = userData.avatar.s;\r\n } else {\r\n // Reset to default avatar or remove src\r\n avatarElement.src = '';\r\n }\r\n }\r\n}\r\n}\r\n\nvar spotFixShowDelayTimeout = null;\r\nconst SPOTFIX_DEBUG = false;\r\nconst SPOTFIX_SHOW_DELAY = 1000;\r\n\r\nif( document.readyState !== 'loading' ) {\r\n document.addEventListener('spotFixLoaded', spotFixInit);\r\n} else {\r\n document.addEventListener('DOMContentLoaded', spotFixInit);\r\n}\r\n\r\nfunction spotFixInit() {\r\n spotfixIndexedDB.init();\r\n wsSpotfix.connect();\r\n wsSpotfix.subscribe();\r\n new SpotFixSourcesLoader();\r\n new CleanTalkWidgetDoboard({}, 'wrap');\r\n loadBotDetector()\r\n}\r\n\r\nfunction loadBotDetector() {\r\nif (document.querySelector('script[src=\"https://moderate.cleantalk.org/ct-bot-detector-wrapper.js\"]') ||\r\n document.getElementById('ct-bot-detector-script')) {\r\n return;\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.src = 'https://moderate.cleantalk.org/ct-bot-detector-wrapper.js';\r\n script.async = true;\r\n script.id = 'ct-bot-detector-script';\r\n document.head.appendChild(script);\r\n}\r\n\r\ndocument.addEventListener('selectionchange', function(e) {\r\n // Do not run widget for non-document events (i.e. inputs focused)\r\n\r\n if (e.target !== document) {\r\n return;\r\n }\r\n\r\n const isWrapReviewWidgetExists = !!(document.getElementsByClassName('wrap_review')[0]);\r\n const sel = document.getSelection();\r\n\r\n if ((!sel || sel.toString() === \"\") && isWrapReviewWidgetExists) {\r\n new CleanTalkWidgetDoboard({}, 'wrap')\r\n return;\r\n }\r\n\r\n if (spotFixShowDelayTimeout) {\r\n clearTimeout(spotFixShowDelayTimeout);\r\n }\r\n\r\n spotFixShowDelayTimeout = setTimeout(() => {\r\n const selection = window.getSelection();\r\n if (\r\n selection.type === 'Range'\r\n ) {\r\n // Check if selection is inside the widget\r\n let anchorNode = selection.anchorNode;\r\n let focusNode = selection.focusNode;\r\n if (spotFixIsInsideWidget(anchorNode) || spotFixIsInsideWidget(focusNode)) {\r\n return;\r\n }\r\n const selectedData = spotFixGetSelectedData(selection);\r\n\r\n if ( selectedData ) {\r\n // spotFixOpenWidget(selectedData, 'create_issue');\r\n spotFixOpenWidget(selectedData, 'wrap_review');\r\n }\r\n }\r\n }, SPOTFIX_SHOW_DELAY);\r\n});\r\n\r\n\r\n/**\r\n * Shows the spot fix widget.\r\n */\r\nfunction spotFixShowWidget() {\r\n new CleanTalkWidgetDoboard(null, 'create_issue');\r\n}\r\n\r\n/**\r\n * Check if a node is inside the task widget.\r\n * @param {*} node\r\n * @returns {boolean}\r\n */\r\nfunction spotFixIsInsideWidget(node) {\r\n if (!node) return false;\r\n let el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\r\n while (el) {\r\n if (el.classList && el.classList.contains('doboard_task_widget')) {\r\n return true;\r\n }\r\n el = el.parentElement;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Open the widget to create a task.\r\n * @param {*} selectedData\r\n * @param {*} type\r\n */\r\nfunction spotFixOpenWidget(selectedData, type) {\r\n if (selectedData) {\r\n new CleanTalkWidgetDoboard(selectedData, type);\r\n }\r\n}\r\n\r\n/**\r\n * Write message into the console.\r\n *\r\n * @param {string} message\r\n */\r\nfunction spotFixDebugLog(message) {\r\n if ( SPOTFIX_DEBUG ) {\r\n console.log(message);\r\n }\r\n}\r\n\r\nfunction hideContainersSpinner() {\r\n const spinners = document.getElementsByClassName('doboard_task_widget-spinner_wrapper_for_containers');\r\n if (spinners.length > 0) {\r\n for (let i = 0; i < spinners.length ; i++) {\r\n spinners[i].style.display = 'none';\r\n }\r\n }\r\n const containerClassesToShow = ['doboard_task_widget-all_issues-container', 'doboard_task_widget-concrete_issues-container'];\r\n for (let i = 0; i < containerClassesToShow.length ; i++) {\r\n const containers = document.getElementsByClassName(containerClassesToShow[i]);\r\n if (containers.length > 0) {\r\n for (let i = 0; i < containers.length ; i++) {\r\n containers[i].style.display = 'block';\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction getTaskFullDetails(tasksDetails, taskId) {\r\n const comments = tasksDetails.comments.filter(comment => {\r\n return comment?.taskId?.toString() === taskId?.toString()\r\n });\r\n const users = tasksDetails.users;\r\n // Last comment\r\n let lastComment = comments.length > 0 ? comments[0] : null;\r\n // Author of the last comment\r\n let author = null;\r\n if (lastComment && users && users.length > 0) {\r\n author = users.find(u => String(u.user_id) === String(lastComment.userId));\r\n }\r\n // Format date\r\n let date = '', time = '';\r\n if (lastComment) {\r\n const dt = formatDate(lastComment.commentDate);\r\n date = dt.date;\r\n time = dt.time;\r\n }\r\n // Get the avatar and the name through separate functions\r\n let avatarSrc = getAvatarSrc(author);\r\n let authorName = getAuthorName(author);\r\n\r\n return {\r\n taskId: taskId,\r\n taskAuthorAvatarImgSrc: avatarSrc,\r\n taskAuthorName: authorName,\r\n lastMessageText: lastComment ? lastComment.commentBody : 'No messages yet',\r\n lastMessageTime: time,\r\n issueTitle: comments.length > 0 ? comments[0].issueTitle : 'No Title',\r\n issueComments: comments\r\n .sort((a, b) => {\r\n return new Date(a.commentDate) - new Date(b.commentDate);\r\n })\r\n .map(comment => {\r\n const {date, time} = formatDate(comment.commentDate);\r\n let author = null;\r\n if (users && users.length > 0) {\r\n author = users.find(u => String(u.user_id) === String(comment.userId));\r\n }\r\n return {\r\n commentAuthorAvatarSrc: getAvatarSrc(author),\r\n commentAuthorName: getAuthorName(author),\r\n commentBody: comment.commentBody,\r\n commentDate: date,\r\n commentTime: time,\r\n commentUserId: comment.userId || 'Unknown User',\r\n };\r\n })\r\n };\r\n}\r\n\r\nfunction getAvatarData(authorDetails) {\r\n let avatarStyle;\r\n let avatarCSSClass;\r\n let taskAuthorInitials =\r\n authorDetails.taskAuthorName && authorDetails.taskAuthorName != 'Anonymous'\r\n ? authorDetails.taskAuthorName.trim().charAt(0).toUpperCase()\r\n : null;\r\n let initialsClass = 'doboard_task_widget-avatar-initials';\r\n if (authorDetails.taskAuthorAvatarImgSrc === null && taskAuthorInitials !== null) {\r\n avatarStyle = 'display: flex;background-color: #f8de7e;justify-content: center;align-items: center;';\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n }\r\n if (authorDetails.taskAuthorAvatarImgSrc === null && taskAuthorInitials === null) {\r\n avatarStyle = `background-image:url(\\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAE9GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4wLWMwMDAgNzkuMTcxYzI3ZmFiLCAyMDIyLzA4LzE2LTIyOjM1OjQxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjQuMCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjQtMDQtMTBUMTk6MDg6MDkrMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI0LTA0LTEwVDE5OjIxOjA4KzA1OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxNWRjOWI0Yy04ZWVmLTRkNTEtYmE0MS1kOTkzZTZmNjNmMTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTVkYzliNGMt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');`;\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n initialsClass += ' doboard_task_widget-hidden_element';\r\n }\r\n if (authorDetails.taskAuthorAvatarImgSrc !== null) {\r\n avatarStyle = `background-image:url(\\'${authorDetails.taskAuthorAvatarImgSrc}\\');`;\r\n avatarCSSClass = 'doboard_task_widget-avatar_container';\r\n initialsClass = 'doboard_task_widget-hidden_element';\r\n }\r\n return {\r\n avatarStyle: avatarStyle,\r\n avatarCSSClass: avatarCSSClass,\r\n taskAuthorInitials: taskAuthorInitials,\r\n initialsClass: initialsClass\r\n }\r\n}\r\n\r\n/**\r\n * Return first found updated task ID or false if no tasks were updated\r\n * @param allTasksData\r\n * @returns {string[]|false}\r\n */\r\nfunction isAnyTaskUpdated(allTasksData) {\r\n let result = false;\r\n\r\n const updatedtasksIDS = [];\r\n\r\n for (let i = 0; i < allTasksData.length; i++) {\r\n const currentStateOfTask = allTasksData[i];\r\n const issuerId = localStorage.getItem('spotfix_user_id');\r\n if (\r\n currentStateOfTask.taskId &&\r\n currentStateOfTask.taskLastUpdate &&\r\n currentStateOfTask.taskCreatorTaskUser.toString() === issuerId.toString()\r\n ) {\r\n result = storageCheckTaskUpdate(currentStateOfTask.taskId, currentStateOfTask.taskLastUpdate);\r\n if (result) {\r\n updatedtasksIDS.push(currentStateOfTask.taskId.toString());\r\n }\r\n }\r\n }\r\n\r\n return updatedtasksIDS.length === 0 ? false : updatedtasksIDS;\r\n}\r\n\r\n/**\r\n * Check if any of the tasks has updates from site owner (not from the current user and not anonymous)\r\n * @returns {Promise}\r\n */\r\nasync function checkIfTasksHasSiteOwnerUpdates(allTasksData, params) {\r\n const updatedTaskIDs = isAnyTaskUpdated(allTasksData);\r\n let result = false;\r\n if (!updatedTaskIDs) {\r\n return false;\r\n }\r\n for (let i = 0; i < updatedTaskIDs.length; i++) {\r\n const updatedTaskId = updatedTaskIDs[i];\r\n if (typeof updatedTaskId === 'string') {\r\n const updatedTaskData = await getTasksFullDetails(params, [updatedTaskId]);\r\n if (updatedTaskData.comments) {\r\n const lastMessage = updatedTaskData.comments[0];\r\n if (\r\n lastMessage.commentUserId !== undefined &&\r\n lastMessage.commentUserId !== localStorage.getItem('spotfix_user_id') &&\r\n lastMessage.commentAuthorName !== 'Anonymous'\r\n ) {\r\n storageAddUnreadUpdateForTaskID(updatedTaskId);\r\n result = true;\r\n }\r\n }\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if the selection is correct - do not allow to select all page, or several different nesting nodes, or something else\r\n * @param selection\r\n * @return {boolean}\r\n */\r\nfunction isSelectionCorrect(selection) {\r\n return true;\r\n}\r\n\r\n/**\r\n * Sanitize HTML\r\n * @param {*} html\r\n * @param {*} options\r\n * @returns\r\n */\r\nfunction ksesFilter(html, options = false) {\r\n let allowedTags = {\r\n a: true,\r\n b: true,\r\n i: true,\r\n strong: true,\r\n em: true,\r\n ul: true,\r\n ol: true,\r\n li: true,\r\n p: true,\r\n s: true,\r\n br: true,\r\n span: true,\r\n blockquote: true,\r\n pre: true,\r\n div: true,\r\n img: true,\r\n input: true,\r\n label: true,\r\n textarea: true,\r\n button: true,\r\n blockquote: true,\r\n pre: true,\r\n details: true,\r\n summary: true,\r\n };\r\n let allowedAttrs = {\r\n a: ['href', 'title', 'target', 'rel', 'style', 'class'],\r\n span: ['style', 'class', 'id'],\r\n p: ['style', 'class'],\r\n div: ['style', 'class', 'id', 'data-node-path', 'data-task-id'],\r\n img: ['src', 'alt', 'title', 'class', 'style', 'width', 'height'],\r\n input: ['type', 'class', 'style', 'id', 'multiple', 'accept', 'value'],\r\n label: ['for', 'class', 'style'],\r\n textarea: ['class', 'id', 'style', 'rows', 'cols', 'readonly', 'required', 'name'],\r\n button: ['type', 'class', 'style', 'id'],\r\n details: ['class', 'style', 'open'],\r\n summary: ['class', 'style'],\r\n };\r\n\r\n if (options && options.template === 'list_issues') {\r\n allowedTags = { ...allowedTags, br: false };\r\n }\r\n\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(html, 'text/html');\r\n function clean(node) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const tag = node.tagName.toLowerCase();\r\n\r\n if (options) {\r\n if (allowedTags[tag]) {\r\n // Special handling for images in 'concrete_issue_day_content' template (wrap img in link always)\r\n if (tag === 'img' && options.template === 'concrete_issue_day_content' && options.imgFilter) {\r\n const src = node.getAttribute('src') || '';\r\n const alt = node.getAttribute('alt') || '[image]';\r\n const link = doc.createElement('a');\r\n link.href = src;\r\n link.target = '_blank';\r\n link.className = 'doboard_task_widget-img-link';\r\n const img = doc.createElement('img');\r\n img.src = src;\r\n img.alt = alt;\r\n img.className = 'doboard_task_widget-comment_body-img-strict';\r\n link.appendChild(img);\r\n node.parentNode.insertBefore(link, node);\r\n node.remove();\r\n return;\r\n }\r\n }\r\n\r\n if (!allowedTags[tag]) {\r\n // Special handling for images in 'list_issues' template\r\n if (tag === 'img' && options.template === 'list_issues' && options.imgFilter) {\r\n const src = node.getAttribute('src') || '';\r\n const alt = node.getAttribute('alt') || '[image]';\r\n const link = doc.createElement('a');\r\n link.href = src;\r\n link.target = '_blank';\r\n link.textContent = alt;\r\n node.parentNode.insertBefore(link, node);\r\n }\r\n node.remove();\r\n return;\r\n }\r\n }\r\n\r\n // Remove disallowed attributes\r\n [...node.attributes].forEach(attr => {\r\n const attrName = attr.name.toLowerCase();\r\n if (!allowedAttrs[tag]?.includes(attrName) ||\r\n attrName.startsWith('on') || // Remove event handlers\r\n attr.value.toLowerCase().includes('javascript:')) {\r\n node.removeAttribute(attr.name);\r\n }\r\n });\r\n }\r\n // Recursively clean children\r\n [...node.childNodes].forEach(clean);\r\n }\r\n [...doc.body.childNodes].forEach(clean);\r\n return doc.body.innerHTML;\r\n}\r\n\n/**\r\n * SELECTION will be grouped into three types:\r\n * 1 - Simple text within a single tag\r\n * 2 - Image tags\r\n * 3 - Any tag containing nested content\r\n * Each type will be processed differently.\r\n */\r\nconst SPOTFIX_SELECTION_TYPE_TEXT = 'text';\r\nconst SPOTFIX_SELECTION_TYPE_IMG = 'image';\r\nconst SPOTFIX_SELECTION_TYPE_ELEMENT = 'element';\r\n\r\n/**\r\n * Determines the type of selection\r\n * @param {Selection} selection - The DOM Selection object\r\n * @returns {string|null} Selection type\r\n */\r\nfunction spotFixGetSelectionType(selection) {\r\n const range = selection.getRangeAt(0);\r\n const commonAncestor = range.commonAncestorContainer;\r\n\r\n // Case 1: Image selection\r\n if (spotFixGetSelectedImage(selection)) {\r\n return SPOTFIX_SELECTION_TYPE_IMG;\r\n }\r\n\r\n // Case 2: Element with nested content\r\n if (commonAncestor.nodeType === Node.ELEMENT_NODE &&\r\n commonAncestor.childNodes.length > 1 &&\r\n range.toString().trim() === '' &&\r\n range.startContainer === range.endContainer &&\r\n range.startContainer.nodeType === Node.ELEMENT_NODE) {\r\n return SPOTFIX_SELECTION_TYPE_ELEMENT;\r\n }\r\n\r\n // Case 3: Simple text\r\n const hasTextContent = range.toString().trim().length > 0;\r\n const isTextNode = commonAncestor.nodeType === Node.TEXT_NODE;\r\n const isCollapsed = range.collapsed;\r\n\r\n if (hasTextContent && (isTextNode || !isCollapsed)) {\r\n return SPOTFIX_SELECTION_TYPE_TEXT;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extracts selection data from DOM Selection object\r\n * @param {Selection} selection - The DOM Selection object\r\n * @returns {Object|null} Selection data with text, positions, URL and node path OR null (nothing)\r\n */\r\nfunction spotFixGetSelectedData(selection) {\r\n // Prechecks:\r\n // Selection not provided\r\n if (!selection) {spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection not provided`'); return null; }\r\n // Range not provided\r\n if (selection.rangeCount === 0) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Range not provided`'); return null; }\r\n // Several ranges provided\r\n if (selection.rangeCount > 1) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Several ranges provided`'); return null; }\r\n\r\n const range = selection.getRangeAt(0);\r\n // Selection must be within a single DOM element.\r\n if (range.startContainer !== range.endContainer) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection within several tags nodes`'); return null; }\r\n\r\n // FIRST - check selection type\r\n const selectionType = spotFixGetSelectionType(selection);\r\n\r\n // Selection type not determined\r\n if (!selectionType) { spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection type not determined`'); return null; }\r\n\r\n // SECOND - generate selectedData for each selectionType\r\n let selectedText = '';\r\n let startSelectPosition = 0;\r\n let endSelectPosition = 0;\r\n let nodePath = '';\r\n let imageUrl = '';\r\n\r\n const commonNode = range.commonAncestorContainer;\r\n\r\n switch (selectionType) {\r\n case SPOTFIX_SELECTION_TYPE_TEXT:\r\n if (range.toString().trim().length === 0) {\r\n spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection text is empty`');\r\n return null;\r\n }\r\n const commonNodeElement = commonNode.nodeType === Node.ELEMENT_NODE ? commonNode : commonNode.parentElement;\r\n selectedText = range.toString();\r\n startSelectPosition = range.startOffset;\r\n endSelectPosition = range.endOffset;\r\n if ( startSelectPosition === 0 && selectedText.length > endSelectPosition ) {\r\n endSelectPosition = selectedText.length;\r\n }\r\n nodePath = spotFixCalculateNodePath(commonNodeElement);\r\n break;\r\n\r\n case SPOTFIX_SELECTION_TYPE_IMG:\r\n const imgElement = range.startContainer;\r\n const selectedImage = spotFixGetSelectedImage(selection);\r\n selectedText = `Image (${selectedImage.alt ? selectedImage.alt : 'no description'})`;\r\n nodePath = spotFixCalculateNodePath(selectedImage);\r\n // For images, positions represent the image element position in parent\r\n startSelectPosition = Array.from(imgElement.parentNode.children).indexOf(imgElement);\r\n endSelectPosition = startSelectPosition + 1;\r\n break;\r\n\r\n case SPOTFIX_SELECTION_TYPE_ELEMENT:\r\n const element = commonNode.nodeType === Node.ELEMENT_NODE ? commonNode : commonNode.parentElement;\r\n if (element.childNodes.length <= 1) {\r\n spotFixDebugLog('`spotFixGetSelectedData` skip by `Selection have not inner data`');\r\n return null;\r\n }\r\n selectedText = element.textContent || '';\r\n nodePath = spotFixCalculateNodePath(element);\r\n // For elements, positions represent the element's position in parent\r\n startSelectPosition = Array.from(element.parentNode.children).indexOf(element);\r\n endSelectPosition = startSelectPosition + 1;\r\n break;\r\n }\r\n\r\n // Get page URL\r\n const pageURL = window.location.href;\r\n\r\n return {\r\n startSelectPosition,\r\n endSelectPosition,\r\n selectedText: selectedText.trim(),\r\n pageURL,\r\n nodePath,\r\n selectionType,\r\n imageUrl: selectionType === SPOTFIX_SELECTION_TYPE_IMG ? imageUrl : ''\r\n };\r\n}\r\n\r\n/**\r\n * Highlight elements.\r\n * @param {[object]} spotsToBeHighlighted\r\n * @param widgetInstance\r\n */\r\nfunction spotFixHighlightElements(spotsToBeHighlighted, widgetInstance) {\r\n\r\n if (spotsToBeHighlighted.length === 0) return;\r\n\r\n const elementsMap = new Map();\r\n\r\n // Grouping elements with validation\r\n spotsToBeHighlighted.forEach(spot => {\r\n // nodePath validating: is array\r\n if (!spot?.nodePath || !Array.isArray(spot?.nodePath)) {\r\n spotFixDebugLog('Invalid spot: missing or invalid nodePath: ' + spot);\r\n return;\r\n }\r\n\r\n // nodePath validating: is valid indexes list\r\n if (!this.spotFixIsValidNodePath(spot.nodePath)) {\r\n spotFixDebugLog('Invalid nodePath format: ' + spot.nodePath);\r\n return;\r\n }\r\n\r\n const element = spotFixRetrieveNodeFromPath(spot.nodePath);\r\n if (!element) {\r\n spotFixDebugLog('Element not found for path: ' + spot.nodePath);\r\n return;\r\n }\r\n\r\n if ( ! spot.selectionType ) {\r\n // @ToDo need to apply backward capability here\r\n // just `spot.selectionType = 'text';` is not able, this opens ability to unauthorized modify website content\r\n spotFixDebugLog('Selection type is not provided.');\r\n return;\r\n }\r\n\r\n // selectionType parameter validating\r\n if (\r\n spot.selectionType &&\r\n ![\r\n SPOTFIX_SELECTION_TYPE_TEXT,\r\n SPOTFIX_SELECTION_TYPE_IMG,\r\n SPOTFIX_SELECTION_TYPE_ELEMENT\r\n ].includes(spot.selectionType)\r\n ) {\r\n spotFixDebugLog('Invalid selection type: ' + spot.selectionType);\r\n return;\r\n }\r\n\r\n if (!elementsMap.has(element)) {\r\n elementsMap.set(element, []);\r\n }\r\n elementsMap.get(element).push(spot);\r\n });\r\n\r\n elementsMap.forEach((spots, element) => {\r\n const selectionType = spots[0].selectionType;\r\n\r\n // MAIN LOGIC: highlight for the different types\r\n switch (selectionType) {\r\n case 'image':\r\n this.spotFixHighlightImageElement(element);\r\n break;\r\n\r\n case 'element':\r\n this.spotFixHighlightNestedElement(element);\r\n break;\r\n\r\n case 'text':\r\n this.spotFixHighlightTextInElement(element, spots, widgetInstance);\r\n break;\r\n\r\n default:\r\n spotFixDebugLog('Unknown selection type: ' + selectionType);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Highlight image element by adding class\r\n * @param {Element} element\r\n */\r\nfunction spotFixHighlightImageElement(element) {\r\n if (element.tagName !== 'IMG') {\r\n spotFixDebugLog('Expected IMG element for image highlight, got: ' + element.tagName);\r\n return;\r\n }\r\n element.classList.add('doboard_task_widget-image_selection');\r\n}\r\n\r\n/**\r\n * Highlight nested element by adding class\r\n * @param {Element} element\r\n */\r\nfunction spotFixHighlightNestedElement(element) {\r\n element.classList.add('doboard_task_widget-element_selection');\r\n}\r\n\r\n/**\r\n * Highlight text in element with span wrapping\r\n * @param {Element} element\r\n * @param {Array} spots\r\n * @param widgetInstance\r\n */\r\nfunction spotFixHighlightTextInElement(element, spots,widgetInstance) {\r\n let tooltipTitleText = '';\r\n if (spots[0].isFixed) {\r\n tooltipTitleText = `This issue already fixed.`;\r\n } else {\r\n tooltipTitleText = `We are already working on this issue.`;\r\n }\r\n\r\n const tooltip = `\r\n
\r\n
\r\n ${tooltipTitleText}
\r\n You can see history Here
\r\n \r\n
`;\r\n\r\n const spotfixHighlightOpen = `${tooltip} `;\r\n const spotfixHighlightClose = ` `;\r\n\r\n let text = element.textContent;\r\n const spotSelectedText = spots[0].selectedText;\r\n\r\n // meta.selectedText can not be empty string\r\n if ( ! spotSelectedText ) {\r\n spotFixDebugLog('Provided metadata is invalid.');\r\n return;\r\n }\r\n\r\n const markers = [];\r\n\r\n // Mark positions for inserting\r\n spots.forEach(spot => {\r\n // Validating positions\r\n const startPos = parseInt(spot.startSelectPosition) || 0;\r\n const endPos = parseInt(spot.endSelectPosition) || 0;\r\n\r\n if (startPos < 0 || endPos > text.length || startPos > endPos) {\r\n spotFixDebugLog('Invalid text positions: ' + spot);\r\n return;\r\n }\r\n\r\n markers.push({ position: startPos, type: 'start' });\r\n markers.push({ position: endPos, type: 'end' });\r\n });\r\n\r\n if (markers.length === 0) return;\r\n\r\n // Sort markers backward\r\n markers.sort((a, b) => b.position - a.position);\r\n\r\n // Check here that element (from meta.nodePath) contains same inner text as in meta.selectedText\r\n // Is the `text` in the element equal to the selected text `spotSelectedText`\r\n if ( text.slice(markers[1].position, markers[0].position) !== spotSelectedText ) {\r\n spotFixDebugLog('It is not allow to highlight element by provided metadata.');\r\n return;\r\n }\r\n\r\n let result = text;\r\n markers.forEach(marker => {\r\n const insertText = marker.type === 'start'\r\n ? spotfixHighlightOpen\r\n : spotfixHighlightClose;\r\n\r\n result = result.slice(0, marker.position) + insertText + result.slice(marker.position);\r\n });\r\n\r\n // Safety HTML insert\r\n try {\r\n element.innerHTML = ksesFilter(result);\r\n document.querySelectorAll('.doboard_task_widget-see-task').forEach(link => {\r\n link.addEventListener('click', (e) => {\r\n\r\n e.preventDefault();\r\n const classList = link.className.split(' ');\r\n const idClass = classList.find(cls => cls.includes('__task-id-'));\r\n let taskId = null;\r\n if (idClass) {\r\n taskId = idClass.split('__task-id-')[1];\r\n }\r\n if (taskId) {\r\n widgetInstance.currentActiveTaskId = taskId;\r\n widgetInstance.showOneTask();\r\n }\r\n });\r\n });\r\n } catch (error) {\r\n spotFixDebugLog('Error updating element content: ' + error);\r\n }\r\n}\r\n\r\n/**\r\n * Scroll to an element by tag, class, and text content\r\n * @param {array} path - The path to the element\r\n * @return {boolean} - True if the element was found and scrolled to, false otherwise\r\n */\r\nfunction spotFixScrollToNodePath(path) {\r\n const node = spotFixRetrieveNodeFromPath(path);\r\n if (node && node.scrollIntoView) {\r\n node.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\nfunction spotFixRemoveHighlights() {\r\n const textSelectionclassName = 'doboard_task_widget-text_selection';\r\n const spans = document.querySelectorAll('.' + textSelectionclassName);\r\n const affectedParents = new Set(); // Track unique parents\r\n\r\n spans.forEach(span => {\r\n const parent = span.parentNode;\r\n affectedParents.add(parent); // Mark parent as affected\r\n const tooltip = span.querySelector('.doboard_task_widget-text_selection_tooltip');\r\n if (tooltip) tooltip.remove();\r\n\r\n // Move all child nodes out of the span and into the parent\r\n while (span.firstChild) {\r\n parent.insertBefore(span.firstChild, span);\r\n }\r\n parent.removeChild(span);\r\n });\r\n\r\n // Normalize all affected parents to merge adjacent text nodes\r\n affectedParents.forEach(parent => parent.normalize());\r\n\r\n const elementSelectionClassName = 'doboard_task_widget-element_selection';\r\n const elements = document.querySelectorAll(`.${elementSelectionClassName}`);\r\n elements.forEach(element => {\r\n element.classList.remove(elementSelectionClassName);\r\n });\r\n const imageSelectionClassName = 'doboard_task_widget-image_selection';\r\n const images = document.querySelectorAll(`.${imageSelectionClassName}`);\r\n images.forEach(element => {\r\n element.classList.remove(imageSelectionClassName);\r\n });\r\n}\r\n\r\n/**\r\n * Validate nodePath as array of indices\r\n * @param {Array} nodePath\r\n * @returns {boolean}\r\n */\r\nfunction spotFixIsValidNodePath(nodePath) {\r\n if (!Array.isArray(nodePath)) return false;\r\n if (nodePath.length === 0) return false;\r\n\r\n return nodePath.every(index => {\r\n return Number.isInteger(index) && index >= 0 && index < 1000;\r\n });\r\n}\r\n\r\n/**\r\n * Try to find selected image in selection.\r\n * @param selection\r\n * @returns {Node|*|null}\r\n */\r\nfunction spotFixGetSelectedImage(selection) {\r\n\r\n if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {\r\n return null;\r\n }\r\n\r\n const range = selection.getRangeAt(0);\r\n\r\n // Is current end container IMG\r\n if (range.startContainer === range.endContainer &&\r\n range.startContainer.nodeType === Node.ELEMENT_NODE &&\r\n range.startContainer.tagName === 'IMG') {\r\n return range.startContainer;\r\n }\r\n\r\n // Get img in the range\r\n const walker = document.createTreeWalker(\r\n range.commonAncestorContainer,\r\n NodeFilter.SHOW_ELEMENT,\r\n {\r\n acceptNode: function(node) {\r\n return node.tagName === 'IMG' &&\r\n spotFixIsElementInRange(node, range) ?\r\n NodeFilter.FILTER_ACCEPT :\r\n NodeFilter.FILTER_REJECT;\r\n }\r\n }\r\n );\r\n\r\n let imgNode = walker.nextNode();\r\n if (imgNode) {\r\n return imgNode;\r\n }\r\n\r\n // start/end containers\r\n const startElement = spotFixGetElementFromNode(range.startContainer);\r\n const endElement = spotFixGetElementFromNode(range.endContainer);\r\n\r\n // If selection starts on image\r\n if (startElement && startElement.tagName === 'IMG' &&\r\n spotFixIsElementPartiallySelected(startElement, range)) {\r\n return startElement;\r\n }\r\n\r\n if (endElement && endElement.tagName === 'IMG' &&\r\n spotFixIsElementPartiallySelected(endElement, range)) {\r\n return endElement;\r\n }\r\n\r\n // 4. Get closest IMG\r\n const nearbyElements = spotFixFindNearbyElements(range);\r\n for (const element of nearbyElements) {\r\n if (element.tagName === 'IMG') {\r\n return element;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction spotFixIsElementInRange(element, range) {\r\n const elementRange = document.createRange();\r\n elementRange.selectNode(element);\r\n return range.compareBoundaryPoints(Range.START_TO_START, elementRange) <= 0 &&\r\n range.compareBoundaryPoints(Range.END_TO_END, elementRange) >= 0;\r\n}\r\n\r\nfunction spotFixIsElementPartiallySelected(element, range) {\r\n const elementRect = element.getBoundingClientRect();\r\n const rangeRect = range.getBoundingClientRect();\r\n\r\n // bounding rectangles is crossed\r\n return !(elementRect.right < rangeRect.left ||\r\n elementRect.left > rangeRect.right ||\r\n elementRect.bottom < rangeRect.top ||\r\n elementRect.top > rangeRect.bottom);\r\n}\r\n\r\nfunction spotFixGetElementFromNode(node) {\r\n return node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\r\n}\r\n\r\n/**\r\n * Find nearby elements in the range.\r\n * @param range\r\n * @returns {*[]}\r\n */\r\nfunction spotFixFindNearbyElements(range) {\r\n const elements = [];\r\n const container = range.commonAncestorContainer;\r\n\r\n // search elements\r\n const previousElement = container.previousElementSibling;\r\n const nextElement = container.nextElementSibling;\r\n\r\n if (previousElement) {\r\n elements.push(previousElement);\r\n }\r\n if (nextElement) {\r\n elements.push(nextElement);\r\n }\r\n\r\n // Also check child container\r\n if (container.nodeType === Node.ELEMENT_NODE) {\r\n const children = container.children;\r\n for (let i = 0; i < children.length; i++) {\r\n if (spotFixIsElementPartiallySelected(children[i], range)) {\r\n elements.push(children[i]);\r\n }\r\n }\r\n }\r\n\r\n return elements;\r\n}\r\n\r\n/**\r\n * Calculate the path of a DOM node\r\n *\r\n * @param {Node} node\r\n * @return {int[]}\r\n */\r\nfunction spotFixCalculateNodePath(node) {\r\n let path = [];\r\n while (node) {\r\n let index = 0;\r\n let sibling = node.previousSibling;\r\n while (sibling) {\r\n if (sibling.nodeType === 1) {\r\n index++;\r\n }\r\n sibling = sibling.previousSibling;\r\n }\r\n path.unshift(index);\r\n node = node.parentNode;\r\n }\r\n\r\n // Hard fix - need to remove first element to work correctly\r\n path.shift();\r\n\r\n return path;\r\n}\r\n\r\n/**\r\n * Retrieve a DOM node from a path\r\n *\r\n * @param {int[]} path\r\n * @return {*|null}\r\n */\r\nfunction spotFixRetrieveNodeFromPath(path) {\r\n // @ToDo check if the path is correct\r\n if ( ! path ) {\r\n return null;\r\n }\r\n\r\n let node = document;\r\n for (let i = 0; i < path.length; i++) {\r\n node = node.children[path[i]];\r\n if ( ! node ) {\r\n return null;\r\n }\r\n }\r\n return node;\r\n}\r\n\n/**\r\n * Return bool if widget is closed in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageGetWidgetIsClosed() {\r\n return localStorage.getItem('spotfix_widget_is_closed') === '1';\r\n}\r\n\r\n/**\r\n * Return bool if widget closed state is defined in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageWidgetCloseIsSet() {\r\n return localStorage.getItem('spotfix_widget_is_closed') !== null;\r\n}\r\n\r\n/**\r\n * Save widget closed state\r\n * @param visible\r\n */\r\nfunction storageSetWidgetIsClosed(visible) {\r\n localStorage.setItem('spotfix_widget_is_closed', visible ? '1' : '0');\r\n if(visible) {\r\n wsSpotfix.close();\r\n } else {\r\n wsSpotfix.connect();\r\n wsSpotfix.subscribe();\r\n }\r\n}\r\n\r\n/**\r\n * Return bool if user is defined in local storage\r\n * @returns {boolean}\r\n */\r\nfunction storageGetUserIsDefined() {\r\n return localStorage.getItem('spotfix_user_id') !== null;\r\n}\r\n\r\n/**\r\n * Save data for updates check\r\n * @param tasks\r\n */\r\nfunction storageSaveTasksUpdateData(tasks) {\r\n if (!tasks || !Array.isArray(tasks)) {\r\n return;\r\n }\r\n\r\n let storedTasks = {};\r\n try {\r\n storedTasks = JSON.parse(localStorage.getItem('spotfix_task_updates') || '{}');\r\n } catch (error) {\r\n storedTasks = {};\r\n }\r\n\r\n tasks.forEach(task => {\r\n if (task.taskId && task.taskLastUpdate) {\r\n storedTasks[task.taskId] = {\r\n taskId: task.taskId,\r\n taskLastUpdate: task.taskLastUpdate\r\n };\r\n }\r\n });\r\n\r\n localStorage.setItem('spotfix_task_updates', JSON.stringify(storedTasks));\r\n}\r\n\r\nfunction storageSaveTasksCount(tasks) {\r\n if (!tasks || !Array.isArray(tasks)) {\r\n return;\r\n }\r\n\r\n const count = tasks.filter(task => {\r\n return task.taskMeta;\r\n })?.length;\r\n\r\n localStorage.setItem('spotfix_tasks_count', `${count}`);\r\n}\r\n\r\n/**\r\n * Check if a specific task has been updated since last check\r\n * @param taskId\r\n * @param currentLastUpdate\r\n * @returns {boolean|null}\r\n */\r\nfunction storageCheckTaskUpdate(taskId, currentLastUpdate) {\r\n if (!taskId || !currentLastUpdate) {\r\n return null;\r\n }\r\n\r\n let storedTasks = {};\r\n try {\r\n storedTasks = JSON.parse(localStorage.getItem('spotfix_task_updates') || '{}');\r\n } catch (error) {\r\n storedTasks = {};\r\n }\r\n const storedTask = storedTasks[taskId];\r\n\r\n if (!storedTask) {\r\n return false;\r\n }\r\n\r\n const storedUpdate = new Date(storedTask.taskLastUpdate);\r\n const currentUpdate = new Date(currentLastUpdate);\r\n return currentUpdate > storedUpdate;\r\n}\r\n\r\n/**\r\n * Add unread update for a specific task\r\n * @param taskId\r\n */\r\nfunction storageAddUnreadUpdateForTaskID(taskId) {\r\n if (!taskId) {\r\n return;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n if (!storedUnread.includes(taskId)) {\r\n storedUnread.push(taskId);\r\n }\r\n\r\n localStorage.setItem('spotfix_unread_updates', JSON.stringify(storedUnread));\r\n}\r\n\r\n/**\r\n * Remove unread update for a specific task\r\n * @param taskId\r\n */\r\nfunction storageRemoveUnreadUpdateForTaskID(taskId) {\r\n if (!taskId) {\r\n return;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n storedUnread = storedUnread.filter(id => id !== taskId);\r\n localStorage.setItem('spotfix_unread_updates', JSON.stringify(storedUnread));\r\n}\r\n\r\n/**\r\n * Check if there are any unread updates\r\n * @returns {boolean}\r\n */\r\nfunction storageTasksHasUnreadUpdates() {\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n return storedUnread.length > 0;\r\n}\r\n\r\n/**\r\n * Check if a specific task has unread updates\r\n * @param taskId\r\n * @returns {boolean}\r\n */\r\nfunction storageProvidedTaskHasUnreadUpdates(taskId) {\r\n if (!taskId) {\r\n return false;\r\n }\r\n\r\n let storedUnread = [];\r\n try {\r\n storedUnread = JSON.parse(localStorage.getItem('spotfix_unread_updates') || '[]');\r\n } catch (error) {\r\n storedUnread = [];\r\n }\r\n\r\n return storedUnread.includes(taskId.toString());\r\n}\r\n\r\nfunction storageSaveSpotfixVersion (version) {\r\n localStorage.setItem('spotfix_app_version', `${version}`);\r\n}\r\n\r\nfunction clearLocalstorageOnLogout () {\r\n localStorage.removeItem('spotfix_email');\r\n localStorage.removeItem('spotfix_session_id');\r\n localStorage.removeItem('spotfix_user_id');\r\n localStorage.removeItem('spotfix_accounts');\r\n localStorage.setItem('spotfix_widget_is_closed', '1');\r\n wsSpotfix.close();\r\n}\r\n\n/**\r\n * File uploader handler for managing file attachments with validation and upload capabilities\r\n */\r\nclass FileUploader {\r\n /**\r\n * Create a new FileUploader instance\r\n * @param {function} escapeHtmlHandler - Function to escape HTML strings for security\r\n */\r\n constructor(escapeHtmlHandler) {\r\n /** @type {Array<{id: string, file: File}>} */\r\n this.files = [];\r\n\r\n /** @type {number} Maximum allowed file size in bytes */\r\n this.maxFileSize = 5 * 1024 * 1024; // 5MB\r\n\r\n /** @type {number} Maximum total size for all files in bytes */\r\n this.maxTotalSize = 25 * 1024 * 1024; // 25MB\r\n\r\n /** @type {number} Maximum number of files allowed */\r\n this.maxFiles = 5;\r\n\r\n /** @type {string[]} Allowed MIME types for files */\r\n this.allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'text/plain', 'application/msword'];\r\n\r\n /** @type {function} HTML escaping function for XSS protection */\r\n this.escapeHtmlHandler = escapeHtmlHandler;\r\n\r\n /** @type {string[]} File size units for display */\r\n this.SIZE_UNITS = ['Bytes', 'KB', 'MB', 'GB'];\r\n }\r\n\r\n /**\r\n * Initialize elements and bindings. Should be called only for comments.\r\n * @returns {void}\r\n */\r\n init() {\r\n this.initializeElements();\r\n this.bindFilesInputChange();\r\n }\r\n\r\n /**\r\n * Define widget elements to work with uploader.\r\n * @returns {void}\r\n */\r\n initializeElements() {\r\n /** @type {HTMLInputElement|null} */\r\n this.fileInput = document.getElementById('doboard_task_widget__file-upload__file-input-button');\r\n\r\n /** @type {HTMLElement|null} */\r\n this.fileList = document.getElementById('doboard_task_widget__file-upload__file-list');\r\n\r\n this.uploaderWrapper = document.getElementById('doboard_task_widget__file-upload__wrapper');\r\n\r\n /** @type {HTMLElement|null} */\r\n this.errorMessage = document.getElementById('doboard_task_widget__file-upload__error');\r\n\r\n if (!this.fileInput || !this.fileList || !this.errorMessage || this.uploaderWrapper) {\r\n console.warn('File uploader elements not found');\r\n }\r\n }\r\n\r\n /**\r\n * Define hidden file input change to run uploader logic.\r\n * @returns {void}\r\n */\r\n bindFilesInputChange() {\r\n if (this.fileInput) {\r\n this.fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\r\n }\r\n }\r\n\r\n /**\r\n * Bind action to paperclip button.\r\n * @param {HTMLElement} element - The paperclip button element\r\n * @returns {void}\r\n */\r\n bindPaperClipAction(element) {\r\n element.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n if (this.fileInput) {\r\n this.fileInput.click();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Handle file input change event\r\n * @param {Event} event - File input change event\r\n * @returns {void}\r\n */\r\n handleFileInputChange(event) {\r\n this.clearError();\r\n\r\n const selectedFiles = Array.from(event.target.files);\r\n if (this.files.length + selectedFiles.length > this.maxFiles) {\r\n this.showError(`Maximum ${this.maxFiles} files can be attached.`);\r\n return;\r\n }\r\n const validFiles = selectedFiles.filter(file => this.validateFile(file));\r\n\r\n validFiles.forEach(file => this.addFile(file));\r\n\r\n // Reset input to allow selecting same files again\r\n event.target.value = '';\r\n\r\n // show wrapper\r\n this.uploaderWrapper.style.display = 'block';\r\n }\r\n\r\n /**\r\n * Validate a file against upload constraints\r\n * @param {File} file - File to validate\r\n * @returns {boolean} True if file is valid, false otherwise\r\n */\r\n validateFile(file) {\r\n // Check file size\r\n if (file.size > this.maxFileSize) {\r\n this.showError(`File \"${file.name}\" is too large. Maximum size: ${this.formatFileSize(this.maxFileSize)}`);\r\n return false;\r\n }\r\n\r\n // Check total size\r\n const totalSize = this.getTotalSize() + file.size;\r\n if (totalSize > this.maxTotalSize) {\r\n this.showError(`Total files size exceeded. Maximum: ${this.formatFileSize(this.maxTotalSize)}`);\r\n return false;\r\n }\r\n\r\n // Check file type\r\n if (this.allowedTypes.length > 0 && !this.allowedTypes.includes(file.type)) {\r\n this.showError(`File type \"${file.type}\" for \"${file.name}\" is not supported.`);\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Calculate total size of all files\r\n * @returns {number} Total size in bytes\r\n */\r\n getTotalSize() {\r\n return this.files.reduce((sum, fileData) => sum + fileData.file.size, 0);\r\n }\r\n\r\n /**\r\n * Add a file to the upload queue\r\n * @param {File} file - File to add\r\n * @returns {void}\r\n */\r\n addFile(file) {\r\n const fileWithId = {\r\n id: this.generateFileId(),\r\n file: file\r\n };\r\n\r\n this.files.push(fileWithId);\r\n this.renderFileList();\r\n }\r\n\r\n /**\r\n * Generate a unique file ID\r\n * @returns {string} Unique file identifier\r\n * @private\r\n */\r\n generateFileId() {\r\n return Date.now() + Math.random().toString(36).substr(2, 9);\r\n }\r\n\r\n /**\r\n * Remove a file from the upload queue\r\n * @param {string} fileId - ID of the file to remove\r\n * @returns {void}\r\n */\r\n removeFile(fileId) {\r\n this.files = this.files.filter(f => f.id !== fileId);\r\n this.renderFileList();\r\n this.clearError();\r\n }\r\n\r\n /**\r\n * Render the file list in the UI\r\n * @returns {void}\r\n */\r\n renderFileList() {\r\n if (!this.fileList) return;\r\n\r\n if (this.files.length === 0) {\r\n this.fileList.innerHTML = ksesFilter('No files attached
');\r\n return;\r\n }\r\n\r\n const fileItems = this.files.map(fileData => this.createFileItem(fileData));\r\n this.fileList.innerHTML = ksesFilter('');\r\n fileItems.forEach(item => this.fileList.appendChild(item));\r\n }\r\n\r\n /**\r\n * Create file item element for display\r\n * @param {object} fileData - File data object\r\n * @param {string} fileData.id - File identifier\r\n * @param {File} fileData.file - File object\r\n * @returns {HTMLDivElement} File item DOM element\r\n */\r\n createFileItem(fileData) {\r\n const { file, id } = fileData;\r\n const fileItem = document.createElement('div');\r\n fileItem.className = 'doboard_task_widget__file-upload__file-item';\r\n\r\n fileItem.innerHTML = ksesFilter(`\r\n \r\n × \r\n `);\r\n\r\n const removeBtn = fileItem.querySelector('.doboard_task_widget__file-upload__remove-btn');\r\n removeBtn.addEventListener('click', () => this.removeFile(id));\r\n\r\n return fileItem;\r\n }\r\n\r\n /**\r\n * Format file size for display\r\n * @param {number} bytes - File size in bytes\r\n * @returns {string} Formatted file size string\r\n */\r\n formatFileSize(bytes) {\r\n if (bytes === 0) return '0 Bytes';\r\n\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + this.SIZE_UNITS[i];\r\n }\r\n\r\n /**\r\n * Show uploader error message\r\n * @param {string} message - Error message to display\r\n * @returns {void}\r\n */\r\n showError(message) {\r\n if (this.errorMessage) {\r\n this.errorMessage.textContent = message;\r\n this.errorMessage.style.display = 'block';\r\n }\r\n }\r\n\r\n /**\r\n * Clear uploader error message\r\n * @returns {void}\r\n */\r\n clearError() {\r\n if (this.errorMessage) {\r\n this.errorMessage.textContent = '';\r\n this.errorMessage.style.display = 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Check if there are files to send\r\n * @returns {boolean} True if files are present, false otherwise\r\n */\r\n hasFiles() {\r\n return this.files.length > 0;\r\n }\r\n\r\n /**\r\n * Clear all files from upload queue\r\n * @returns {void}\r\n */\r\n clearFiles() {\r\n this.files = [];\r\n this.renderFileList();\r\n }\r\n\r\n /**\r\n * Validate file data structure before upload\r\n * @param {object} fileData - File data object to validate\r\n * @param {string} fileData.sessionId - Session identifier\r\n * @param {object} fileData.params - Additional parameters\r\n * @param {string} fileData.params.accountId - Account identifier\r\n * @param {string} fileData.params.projectToken - Project token\r\n * @param {string} fileData.commentId - Comment identifier\r\n * @param {string} fileData.fileName - File name\r\n * @param {File} fileData.fileBinary - File binary data\r\n * @returns {object} Validated file data\r\n * @throws {Error} When file data validation fails\r\n */\r\n validateFileData(fileData) {\r\n const validations = [\r\n { field: 'sessionId', type: 'string', message: 'No valid session found.' },\r\n { field: 'params.accountId', type: 'string', message: 'No valid account ID found.' },\r\n { field: 'params.projectToken', type: 'string', message: 'No valid project token found.' },\r\n { field: 'commentId', type: 'string', message: 'No valid commentId found.' },\r\n { field: 'fileName', type: 'string', message: 'No valid filename found.' }\r\n ];\r\n\r\n for (const validation of validations) {\r\n const value = this.getNestedValue(fileData, validation.field);\r\n if (!value || typeof value !== validation.type) {\r\n throw new Error(validation.message);\r\n }\r\n }\r\n\r\n if (!fileData.fileBinary || !(fileData.fileBinary instanceof File)) {\r\n throw new Error('No valid file object found.');\r\n }\r\n\r\n return fileData;\r\n }\r\n\r\n /**\r\n * Helper to get nested object values\r\n * @param {object} obj - Object to traverse\r\n * @param {string} path - Dot notation path to value\r\n * @returns {*} Value at the specified path\r\n * @private\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => current?.[key], obj);\r\n }\r\n\r\n /**\r\n * Send single file attachment\r\n * @param {object} fileData - File data for upload\r\n * @returns {Promise} Upload response\r\n */\r\n async sendSingleAttachment(fileData) {\r\n const validatedFileData = await this.validateFileData(fileData);\r\n return await attachmentAddDoboard(validatedFileData);\r\n }\r\n\r\n /**\r\n * Send all attachments for a comment\r\n * @param {object} params - Upload parameters\r\n * @param {string} sessionId - Session identifier\r\n * @param {string} commentId - Comment identifier\r\n * @returns {Promise} Upload results\r\n */\r\n async sendAttachmentsForComment(params, sessionId, commentId) {\r\n /** @type {object} */\r\n const results = {\r\n preparedFilesCount: this.files.length,\r\n sentFilesCount: 0,\r\n fileResults: [],\r\n success: true\r\n };\r\n\r\n for (let i = 0; i < this.files.length; i++) {\r\n const fileData = this.files[i];\r\n /** @type {object} */\r\n const result = {\r\n success: false,\r\n response: null,\r\n error: null\r\n };\r\n\r\n try {\r\n const attachmentData = {\r\n params,\r\n sessionId,\r\n commentId,\r\n fileName: fileData.file.name,\r\n fileBinary: fileData.file,\r\n attachmentOrder: i\r\n };\r\n\r\n const response = await this.sendSingleAttachment(attachmentData);\r\n result.response = response;\r\n result.success = response.status === 200;\r\n\r\n if (result.success) {\r\n results.sentFilesCount++;\r\n }\r\n } catch (error) {\r\n result.error = error.message;\r\n }\r\n\r\n results.fileResults.push(result);\r\n }\r\n\r\n results.success = results.preparedFilesCount === results.sentFilesCount;\r\n this.clearFiles();\r\n\r\n return results;\r\n }\r\n}\r\n\nclass SpotFixTemplatesLoader {\r\n static getTemplateCode(templateName) {\r\n const templateMethod = this[templateName];\r\n\r\n if (typeof templateMethod !== 'function') {\r\n throw new Error(`Template method '${templateName}' not found`);\r\n }\r\n\r\n let template = templateMethod.call(this).trim();\r\n\r\n return template;\r\n }\r\n\r\n static all_issues() {\r\n return `\r\n`;\r\n }\r\n\r\n static concrete_issue() {\r\n return `\r\n\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n`;\r\n }\r\n\r\n static concrete_issue_day_content() {\r\n return `\r\n\r\n
{{dayContentMonthDay}}
\r\n
{{dayContentMessages}}
\r\n {{statusFixedHtml}}\r\n
\r\n`;\r\n }\r\n\r\n static concrete_issue_messages() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static create_issue() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static list_issues() {\r\n return `\r\n\r\n`;\r\n }\r\n\r\n static user_menu() {\r\n return `\r\n`;\r\n }\r\n\r\n static wrap() {\r\n return `\r\n`;\r\n }\r\n\r\n static wrap_review() {\r\n return `\r\n\r\n \r\nReview content \r\n `;\r\n }\r\n\r\n static fixedHtml() {\r\n return `Finished
`;\r\n }\r\n static fixedTaskHtml() {\r\n return `This issue already fixed
`;\r\n }\r\n\r\n}\r\n\nclass SpotFixSVGLoader {\r\n static loadSVG(svgName) {\r\n const svgMethod = this[svgName];\r\n\r\n if (typeof svgMethod !== 'function') {\r\n throw new Error(`Template method '${svgName}' not found`);\r\n }\r\n\r\n return svgMethod.call(this).trim();\r\n }\r\n\r\n static getAsRawSVG(svgName) {\r\n return this.loadSVG(svgName);\r\n }\r\n\r\n static getAsDataURI(svgName) {\r\n const svg = this.loadSVG(svgName);\r\n return this.svgToDataURI(svg);\r\n }\r\n\r\n static svgToDataURI(svgString) {\r\n const bytes = new TextEncoder().encode(svgString);\r\n const baseBtoa = btoa(String.fromCharCode(...bytes));\r\n return `data:image/svg+xml;base64,${baseBtoa}`;\r\n }\r\n\r\n static chevronBack() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static chevronBackDark() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static buttonCloseScreen() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static buttonSendMessage() {\r\n return `\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n }\r\n\r\n static buttonPaperClip() {\r\n return `\r\n\r\n \r\n `;\r\n }\r\n\r\n static logoDoBoardGreen() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static logoDoBoardWrap() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotPublic() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotPrivate() {\r\n return `\r\n\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconSpotWidgetWrapPencil() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconLinkChain() {\r\n return `\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconEllipsesMore() {\r\n return `\r\n\r\n\r\n\r\n `;\r\n }\r\n\r\n static iconAvatar() {\r\n return `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n }\r\n\r\n static iconEye() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconDoor() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconPlus() {\r\n return `\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconMaximize() {\r\n return `\r\n\r\n\r\n\r\n\r\n \r\n`;\r\n }\r\n\r\n static iconMarker() {\r\n return ` `;\r\n }\r\n}\r\n\nclass SpotFixSourcesLoader {\r\n\r\n constructor() {\r\n this.loadAll();\r\n }\r\n\r\n getCSSCode() {\r\n // global gulp wrapper var\r\n return spotFixCSS;\r\n }\r\n\r\n loadAll() {\r\n this.loadFonts();\r\n this.loadCSS();\r\n };\r\n\r\n loadFonts() {\r\n const preconnect_first = document.createElement('link');\r\n preconnect_first.rel = 'preconnect';\r\n preconnect_first.href = 'https://fonts.googleapis.com';\r\n document.head.appendChild(preconnect_first);\r\n\r\n const preconnect_second = document.createElement('link');\r\n preconnect_second.rel = 'preconnect';\r\n preconnect_second.href = 'https://fonts.gstatic.com';\r\n preconnect_second.crossOrigin = 'crossorigin';\r\n document.head.appendChild(preconnect_second);\r\n\r\n const fontLink = document.createElement('link');\r\n fontLink.rel = 'stylesheet';\r\n fontLink.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap';\r\n document.head.appendChild(fontLink);\r\n }\r\n\r\n loadCSS() {\r\n const style = document.createElement('style');\r\n style.setAttribute('id', 'spotfix_css');\r\n style.textContent = this.getCSSCode();\r\n document.head.appendChild(style);\r\n }\r\n}\r\n\ndocument.dispatchEvent(new CustomEvent('spotFixLoaded', {\r\n detail: {\r\n timestamp: new Date().toISOString(),\r\n message: 'All scripts loaded successfully'\r\n }\r\n}));\r\n"],"names":["INDEXED_DB_NAME","indexedDBVersion","TABLE_USERS","TABLE_TASKS","TABLE_COMMENTS","LOCAL_DATA_BASE_TABLE","name","keyPath","async","openIndexedDB","version","Promise","resolve","reject","request","indexedDB","open","onsuccess","result","onerror","error","onupgradeneeded","deleteDB","db","await","window","databases","deleteReq","deleteDatabase","err","console","warn","spotfixIndexedDB","getIndexedDBName","localStorage","getItem","init","sessionId","projectToken","needInit","dbName","e","target","forEach","store","objectStoreNames","contains","item","createObjectStore","createIndex","missingStores","filter","length","close","newVersion","upgradeRequest","db2","e2","withStore","table","mode","callback","transaction","objectStore","oncomplete","put","data","Array","isArray","delete","key","clearTable","clear","clearPut","getAll","indexName","value","let","undefined","index","getTable","deleteTable","SPOTFIX_DOBOARD_API_URL","spotfixApiCall","method","accountId","Error","formData","FormData","hasOwnProperty","append","endpointUrl","URL","response","fetch","body","networkError","message","responseBody","json","parseError","operation_status","errorMessage","operation_message","clearLocalstorageOnLogout","checkLogInOutButtonsVisible","userConfirmEmailDoboard","emailConfirmationToken","email_confirmation_token","encodeURIComponent","session_id","userId","user_id","email","accounts","operationStatus","createTaskDoboard","taskDetails","project_token","project_id","projectId","taskTitle","comment","taskDescription","meta","taskMeta","task_type","taskId","task_id","createTaskCommentDoboard","status","commentId","comment_id","attachmentAddDoboard","fileData","params","account_id","filename","fileName","file","fileBinary","attachment_order","attachmentOrder","registerUserDoboard","nickname","pageURL","confirmation_url","botDetectorData","JSON","parse","bot_detector_event_token","accountExists","user_email_confirmed","operationMessage","userEmailConfirmed","loginUserDoboard","password","forgotPasswordDoboard","logoutUserDoboard","accountsString","includes","getTasksDoboard","tasks","map","task","taskLastUpdate","updated","taskCreated","created","taskCreatorTaskUser","creator_user_id","taskStatus","storageSaveTasksCount","getTasksCommentsDoboard","comments","commentBody","commentDate","issueTitle","task_name","getUserDoboard","users","userUpdateDoboard","timezone","timestamp","success","getReleaseVersion","tag_name","storageSaveSpotfixVersion","socket","heartbeatInterval","WS_URL","getSessionId","buildMessage","channel","action","wsSpotfix","connect","readyState","WebSocket","OPEN","onopen","setInterval","send","onmessage","event","object","onclose","code","reason","clearInterval","stringify","unsubscribe","subscribe","SPOTFIX_VERSION","spotFixCSS","confirmUserEmail","pendingTaskRaw","setItem","pendingTask","selectedText","description","selectedData","createdTask","handleCreateTask","removeItem","getTasksFullDetails","currentActiveTaskId","find","getUserDetails","currentUserId","user","sign","location","href","addTaskComment","commentText","getUserTasks","getAllTasks","formatDate","dateStr","date","time","dateObj","Date","replace","isNaN","getTime","offsetMinutes","getTimezoneOffset","localDateObj","getMonth","getDate","getHours","toString","padStart","getMinutes","getTaskAuthorDetails","taskAuthorAvatarImgSrc","taskAuthorName","element","getIssuesCounterString","onPageSpotsCount","totalSpotsCount","getAvatarSrc","author","avatar","m","getAuthorName","trim","registerUser","userEmail","userName","then","document","querySelector","innerText","ksesFilter","classList","remove","getElementById","focus","userUpdate","showMessageCallback","submitButton","disabled","catch","loginUser","userPassword","forgotPassword","log","forgotPasswordForm","loginContainer","add","closest","Intl","DateTimeFormat","resolvedOptions","timeZone","spotFixSplitUrl","url","u","domain","segments","reversed","host","pathname","split","Boolean","reverse","push","join","setToggleStatus","rootElement","toggle","checked","addEventListener","timer","setTimeout","hide","clearTimeout","el","style","display","clearUserMenuData","userNameElement","emailElement","avatarElement","src","SpotFixSVGLoader","getAsDataURI","changeSize","container","CleanTalkWidgetDoboard","widgetElement","savedIssuesQuantityOnPage","savedIssuesQuantityAll","allTasksData","srcVariables","constructor","type","this","buttonCloseScreen","iconEllipsesMore","iconPlus","iconMaximize","chevronBack","buttonPaperClip","buttonSendMessage","logoDoBoardGreen","logoDoBoardWrap","iconSpotWidgetWrapPencil","iconMarker","iconSpotPublic","iconSpotPrivate","iconLinkChain","fileUploader","FileUploader","escapeHtml","getParams","urlParams","URLSearchParams","search","emailToken","get","newUrl","storageSetWidgetIsClosed","history","replaceState","title","registrationShowMessage","isWidgetClosed","taskHasSiteOwnerUpdate","storageTasksHasUnreadUpdates","checkIfTasksHasSiteOwnerUpdates","storageSaveTasksUpdateData","storageWidgetCloseIsSet","createWidgetElement","bindWidgetInputsInteractive","script","Object","fromEntries","searchParams","entries","bindCreateTaskEvents","taskTitleElement","taskDescriptionElement","loginSectionElement","userEmailElement","userPasswordElement","borderColor","submitTaskResult","submitTask","cursor","needToLogin","isPublic","hideContainersSpinner","resetLoginForm","phantomContainer","bindShowLoginFormEvents","showLoginButton","showPhantomLoginButton","forgotPasswordButton","forgotPasswordButtonBlack","loginButton","restorePasswordButton","forgotPasswordButtonMenu","forgotPasswordButtonBlackMenu","passwordToggle","test","setUserMenuData","sessionIdExists","passwordInput","isPassword","showOnlyCurrentPage","widgetContainer","createElement","className","innerHTML","removeAttribute","templateName","tasksFullDetails","templateVariables","config","SpotfixWidgetConfig","type_name","currentDomain","hostname","storageGetUserIsDefined","storageGetWidgetIsClosed","position","Number","verticalPosition","spotfixVersion","iconEye","iconDoor","chevronBackDark","issueComments","issuesCounter","loadTemplate","appendChild","spotFixRemoveHighlights","selection","getSelection","spotFixScrollToNodePath","spotFixGetSelectedData","nodePath","positionWidgetContainer","getTaskCount","widgetElementClasses","currentTarget","spotFixOpenWidget","issuesQuantityOnPage","spotsToBeHighlighted","currentURL","sortedTasks","sort","a","b","aIsHere","i","elTask","taskMetaString","taskData","isFixed","taskFullDetails","avatarData","currentPageURL","taskNodePath","taskPublicStatusImgSrc","taskPublicStatusHint","getAvatarData","getTaskFullDetails","listIssuesTemplateVariables","taskLastMessage","lastMessageText","taskPageUrl","taskFormattedPageUrl","lastMessageTime","sanitizeNodePath","avatarCSSClass","avatarStyle","taskAuthorInitials","initialsClass","classUnread","elementBgCSSClass","statusFixedHtml","storageProvidedTaskHasUnreadUpdates","isSpotHaveToBeHighlighted","spotFixHighlightElements","bindIssuesClick","gitHubAppVersion","s","issueTitleElement","currentTaskData","String","origin","issuesCommentsContainer","protocol","contenerClasess","dayMessagesData","initIssuerID","storageRemoveUnreadUpdateForTaskID","userIsIssuer","commentUserId","commentAuthorAvatarSrc","commentAuthorName","commentData","commentTime","issueMessageClassOwner","daysWrapperHTML","day","messageId","currentDayMessages","dayMessagesWrapperHTML","localeCompare","currentMessageTemplateVariables","dayContentMonthDay","dayContentMessages","textarea","handleTextareaChange","contentContainer","scrollTo","top","scrollHeight","behavior","sendButton","widgetClass","preventDefault","input","newCommentResponse","alert","hasFiles","attachmentsSendResult","sendAttachmentsForComment","showError","toConsole","backToAllIssuesController","self","paperclipController","bindPaperClipAction","spotFixShowWidget","querySelectorAll","getAttribute","showOneTask","taskHighlightData","getTaskHighlightData","variables","template","SpotFixTemplatesLoader","getTemplateCode","placeholder","replacement","isPlaceholderInAttribute","imgFilter","replaceAll","escapedPlaceholder","RegExp","unsafe","tasksCountLS","tasksCount","taskCountElement","wrapElementWithSpotfixHighlight","newElement","cloneNode","wrapper","insertAdjacentElement","taskIdToSearch","currentTaskSpotData","accordionController","context","handleScroll","bind","handleResize","messageText","titleSpan","messageDiv","messageWrap","color","widget","widgetCreateIssue","widgetConcreteIssue","scrollY","viewportHeight","innerHeight","selectionAbsoluteTop","getBoundingClientRect","widgetHeight","offsetHeight","bottom","scrollTimeout","resizeTimeout","str","userData","spotFixShowDelayTimeout","SPOTFIX_DEBUG","SPOTFIX_SHOW_DELAY","spotFixInit","SpotFixSourcesLoader","loadBotDetector","id","head","spotFixIsInsideWidget","node","nodeType","Node","ELEMENT_NODE","parentElement","spotFixDebugLog","spinners","getElementsByClassName","containerClassesToShow","containers","tasksDetails","lastComment","dt","avatarSrc","authorName","authorDetails","charAt","toUpperCase","isAnyTaskUpdated","updatedtasksIDS","currentStateOfTask","issuerId","storageCheckTaskUpdate","updatedTaskIDs","lastMessage","updatedTaskId","updatedTaskData","storageAddUnreadUpdateForTaskID","isSelectionCorrect","html","options","allowedTags","strong","em","ul","ol","li","p","br","span","blockquote","pre","div","img","label","button","details","summary","allowedAttrs","doc","DOMParser","parseFromString","childNodes","clean","tag","tagName","toLowerCase","link","alt","parentNode","insertBefore","textContent","attributes","attr","attrName","startsWith","sel","isWrapReviewWidgetExists","focusNode","anchorNode","SPOTFIX_SELECTION_TYPE_TEXT","SPOTFIX_SELECTION_TYPE_IMG","SPOTFIX_SELECTION_TYPE_ELEMENT","spotFixGetSelectionType","range","getRangeAt","commonAncestor","commonAncestorContainer","spotFixGetSelectedImage","startContainer","endContainer","hasTextContent","isTextNode","TEXT_NODE","isCollapsed","collapsed","rangeCount","selectionType","startSelectPosition","endSelectPosition","commonNode","commonNodeElement","startOffset","endOffset","spotFixCalculateNodePath","imgElement","selectedImage","from","children","indexOf","imageUrl","widgetInstance","elementsMap","Map","spot","spotFixIsValidNodePath","spotFixRetrieveNodeFromPath","has","set","spots","spotFixHighlightImageElement","spotFixHighlightNestedElement","spotFixHighlightTextInElement","tooltipTitleText","spotfixHighlightOpen","text","spotSelectedText","markers","startPos","parseInt","endPos","slice","marker","insertText","idClass","cls","path","scrollIntoView","block","spans","affectedParents","Set","elementSelectionClassName","parent","tooltip","firstChild","removeChild","normalize","imageSelectionClassName","every","isInteger","imgNode","createTreeWalker","NodeFilter","SHOW_ELEMENT","acceptNode","spotFixIsElementInRange","FILTER_ACCEPT","FILTER_REJECT","nextNode","startElement","spotFixGetElementFromNode","endElement","spotFixIsElementPartiallySelected","spotFixFindNearbyElements","elementRange","createRange","selectNode","compareBoundaryPoints","Range","START_TO_START","END_TO_END","elementRect","rangeRect","right","left","elements","previousElement","previousElementSibling","nextElement","nextElementSibling","sibling","previousSibling","unshift","shift","visible","storedTasks","count","currentLastUpdate","storedTask","storedUnread","escapeHtmlHandler","files","maxFileSize","maxTotalSize","maxFiles","allowedTypes","SIZE_UNITS","initializeElements","bindFilesInputChange","fileInput","fileList","uploaderWrapper","handleFileInputChange","click","clearError","selectedFiles","validateFile","addFile","size","formatFileSize","getTotalSize","reduce","sum","fileWithId","generateFileId","renderFileList","now","Math","random","substr","removeFile","fileId","f","fileItems","createFileItem","fileItem","bytes","floor","parseFloat","pow","toFixed","clearFiles","validateFileData","validation","field","getNestedValue","File","obj","current","sendSingleAttachment","validatedFileData","results","preparedFilesCount","sentFilesCount","fileResults","attachmentData","templateMethod","call","all_issues","concrete_issue","concrete_issue_day_content","concrete_issue_messages","create_issue","list_issues","user_menu","wrap","wrap_review","fixedHtml","fixedTaskHtml","loadSVG","svgName","svgMethod","getAsRawSVG","svg","svgToDataURI","svgString","TextEncoder","encode","btoa","fromCharCode","iconAvatar","loadAll","getCSSCode","loadFonts","loadCSS","preconnect_first","preconnect_second","rel","fontLink","crossOrigin","setAttribute","dispatchEvent","CustomEvent","detail","toISOString"],"mappings":"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"}
\ No newline at end of file
diff --git a/js/src/api.js b/js/src/api.js
index edbb70b..6e12cfb 100644
--- a/js/src/api.js
+++ b/js/src/api.js
@@ -75,6 +75,11 @@ const spotfixApiCall = async(data, method, accountId = undefined) => {
if (responseBody.data.operation_status === 'FAILED') {
const errorMessage = responseBody.data.operation_message || 'Operation failed without specific message';
+ if(responseBody?.data?.operation_message === 'session_id Unknown'){
+ clearLocalstorageOnLogout();
+ checkLogInOutButtonsVisible();
+ await deleteDB();
+ }
throw new Error(errorMessage);
}
@@ -176,6 +181,7 @@ const registerUserDoboard = async (projectToken, accountId, email, nickname, pag
operationMessage: result.operation_message,
operationStatus: result.operation_status,
userEmailConfirmed: result.user_email_confirmed,
+ accounts: result.accounts,
};
};
@@ -193,11 +199,24 @@ const loginUserDoboard = async (email, password) => {
operationMessage: result.operation_message,
operationStatus: result.operation_status,
userEmailConfirmed: result.user_email_confirmed,
+ accounts: result.accounts
+ }
+}
+
+const forgotPasswordDoboard = async (email) => {
+ const data = {
+ email: email
}
+ return await spotfixApiCall(data, 'user_password_reset');
}
-const logoutUserDoboard = async (projectToken, accountId) => {
+
+const logoutUserDoboard = async (projectToken) => {
const sessionId = localStorage.getItem('spotfix_session_id');
+ const accountsString = localStorage.getItem('spotfix_accounts');
+ const accounts = accountsString !== 'undefined' ? JSON.parse(accountsString || '[]') : [];
+ const accountId = accounts.length > 0 ? accounts[0].account_id : 1;
+
if(sessionId && accountId) {
const data = {
session_id: sessionId,
@@ -214,6 +233,7 @@ const logoutUserDoboard = async (projectToken, accountId) => {
if (result.operation_status === 'SUCCESS') {
await deleteDB();
clearLocalstorageOnLogout();
+ checkLogInOutButtonsVisible();
}
}
}
diff --git a/js/src/handlers.js b/js/src/handlers.js
index 022ff2b..3a33e9a 100644
--- a/js/src/handlers.js
+++ b/js/src/handlers.js
@@ -212,15 +212,23 @@ function registerUser(taskDetails) {
localStorage.setItem('spotfix_session_id', response.sessionId);
localStorage.setItem('spotfix_user_id', response.userId);
localStorage.setItem('spotfix_email', response.email);
+ localStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));
spotfixIndexedDB.init();
userUpdate(projectToken, accountId);
} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {
- if (response.operationMessage == 'Waiting for email confirmation') {
+ if (response.operationMessage === 'Waiting for email confirmation') {
response.operationMessage = 'Waiting for an email confirmation. Please check your Inbox.';
+ if (document.getElementById('doboard_task_widget-error_message').innerText === 'Waiting for an email confirmation. Please check your Inbox.') {
+ response.operationMessage = 'Incorrect email address. Please confirm your email to create the spot.';
+ }
}
if (typeof showMessageCallback === 'function') {
showMessageCallback(response.operationMessage, 'notice');
}
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ submitButton.disabled = true;
+ submitButton.innerText = ksesFilter('Create spot');
+
} else {
throw new Error('Session ID not found in response');
}
@@ -241,7 +249,10 @@ function loginUser(taskDetails) {
if (response.sessionId) {
localStorage.setItem('spotfix_session_id', response.sessionId);
localStorage.setItem('spotfix_user_id', response.userId);
+ localStorage.setItem('spotfix_email', response.email);
localStorage.setItem('spotfix_email', userEmail);
+ localStorage.setItem('spotfix_accounts', JSON.stringify(response.accounts));
+ checkLogInOutButtonsVisible();
spotfixIndexedDB.init();
} else if (response.operationStatus === 'SUCCESS' && response.operationMessage && response.operationMessage.length > 0) {
if (typeof showMessageCallback === 'function') {
@@ -256,6 +267,33 @@ function loginUser(taskDetails) {
});
}
+function forgotPassword(userEmail) {
+ return (showMessageCallback) => forgotPasswordDoboard(userEmail)
+ .then(response => {
+ console.log('response ', response)
+ if (response?.operation_status === 'SUCCESS') {
+ showMessageCallback('New password sent to email', 'notice');
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ } else {
+ throw new Error('Response error');
+ }
+ })
+ .catch(error => {
+ throw error;
+ });
+}
+
function userUpdate(projectToken, accountId) {
const sessionId = localStorage.getItem('spotfix_session_id');
const userId = localStorage.getItem('spotfix_user_id');
@@ -291,7 +329,6 @@ function setToggleStatus(rootElement){
const clickHandler = () => {
const timer = setTimeout(() => {
localStorage.setItem('spotfix_widget_is_closed', '1');
- wsSpotfix.close();
rootElement.hide();
clearTimeout(timer);
}, 300);
@@ -305,13 +342,40 @@ function setToggleStatus(rootElement){
function checkLogInOutButtonsVisible (){
if(!localStorage.getItem('spotfix_session_id')) {
- const el = document
- .getElementById('doboard_task_widget-user_menu-logout_button')
- ?.closest('.doboard_task_widget-user_menu-item');
- if(el) el.style.display = 'none';
- } else {
- const el = document.getElementById('doboard_task_widget-user_menu-signlog_button');
+ const el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');
if(el) el.style.display = 'none';
+
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login')
+ if(loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ clearUserMenuData();
+ } else {
+ const el = document.getElementById('doboard_task_widget-user_menu-logout_button')?.closest('.doboard_task_widget-user_menu-item');
+ if(el) el.style.display = 'block';
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login')
+ if(loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ }
+}
+
+/**
+ * Clear user menu data in menu
+ */
+async function clearUserMenuData() {
+ const userNameElement = document.querySelector('.doboard_task_widget-user_menu-header-user-name');
+ const emailElement = document.querySelector('.doboard_task_widget-user_menu-header-email');
+ const avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');
+
+ if (userNameElement) {
+ userNameElement.innerText = 'Guest';
+ }
+ if (emailElement) {
+ emailElement.innerText = '';
+ }
+ if (avatarElement) {
+ avatarElement.src = SpotFixSVGLoader.getAsDataURI('iconAvatar');
}
}
diff --git a/js/src/loaders/SpotFixTemplatesLoader.js b/js/src/loaders/SpotFixTemplatesLoader.js
index 3d56c16..532efcc 100644
--- a/js/src/loaders/SpotFixTemplatesLoader.js
+++ b/js/src/loaders/SpotFixTemplatesLoader.js
@@ -170,27 +170,64 @@ class SpotFixTemplatesLoader {
- {{userName}}
- {{email}}
-
+
+
@@ -284,6 +318,38 @@ class SpotFixTemplatesLoader {
Log out
+
+
+
+
@@ -293,6 +359,10 @@ class SpotFixTemplatesLoader {
doBoard
+
`;
}
diff --git a/js/src/storage.js b/js/src/storage.js
index 48b87d9..9220adc 100644
--- a/js/src/storage.js
+++ b/js/src/storage.js
@@ -189,6 +189,7 @@ function clearLocalstorageOnLogout () {
localStorage.removeItem('spotfix_email');
localStorage.removeItem('spotfix_session_id');
localStorage.removeItem('spotfix_user_id');
+ localStorage.removeItem('spotfix_accounts');
localStorage.setItem('spotfix_widget_is_closed', '1');
wsSpotfix.close();
}
diff --git a/js/src/widget.js b/js/src/widget.js
index 06c644c..fabd1b0 100644
--- a/js/src/widget.js
+++ b/js/src/widget.js
@@ -157,8 +157,9 @@ class CleanTalkWidgetDoboard {
let userEmail = '';
let userPassword = '';
const loginSectionElement = document.querySelector('.doboard_task_widget-login');
+ const sessionIdExists = !!localStorage.getItem('spotfix_session_id');
- if ( loginSectionElement && loginSectionElement.classList.contains('active') ) {
+ if ( !sessionIdExists && loginSectionElement && loginSectionElement.classList.contains('active') ) {
const userEmailElement = document.getElementById('doboard_task_widget-user_email');
const userNameElement = document.getElementById('doboard_task_widget-user_name');
const userPasswordElement = document.getElementById('doboard_task_widget-user_password');
@@ -271,6 +272,233 @@ class CleanTalkWidgetDoboard {
}
}
+
+ resetLoginForm() {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ }
+ }
+ bindShowLoginFormEvents() {
+ const showLoginButton = document.getElementById('doboard_task_widget-show_login_form');
+ const showPhantomLoginButton = document.getElementById('doboard_task_widget-on_phantom_login_page');
+ const forgotPasswordButton = document.getElementById('doboard_task_widget-forgot_password');
+ const forgotPasswordButtonBlack = document.getElementById('doboard_task_widget-forgot_password-black');
+ const loginButton = document.getElementById('doboard_task_widget-login_button');
+ const restorePasswordButton = document.getElementById('doboard_task_widget-restore_password_button');
+
+ if (showLoginButton) {
+ showLoginButton.addEventListener('click', async () => {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (loginContainer) {
+ loginContainer.classList.toggle('doboard_task_widget-hidden');
+ if (submitButton) {
+ if (loginContainer.classList.contains('doboard_task_widget-hidden')) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ } else {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.toggle('doboard_task_widget-hidden');
+ }
+ })
+ }
+ if (showPhantomLoginButton) {
+ showPhantomLoginButton.addEventListener('click', async () => {
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login');
+ const phantomContainer = document.querySelector('.doboard_task_widget-input-container-phantom');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (loginContainer) {
+ loginContainer.classList.toggle('doboard_task_widget-hidden');
+ if (submitButton) {
+ if (loginContainer.classList.contains('doboard_task_widget-hidden')) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ } else {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ }
+ if (phantomContainer) {
+ phantomContainer.classList.toggle('doboard_task_widget-hidden');
+ }
+ })
+ }
+ if (forgotPasswordButton) {
+ forgotPasswordButton.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.remove('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ })
+
+ forgotPasswordButtonBlack.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.getElementById('doboard_task_widget-input-container-login');
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.add('doboard_task_widget-hidden');
+ }
+ }
+ })
+ }
+ const forgotPasswordButtonMenu = document.querySelector('.doboard_task_widget-input-container-login-menu #doboard_task_widget-forgot_password');
+ if (forgotPasswordButtonMenu) {
+ forgotPasswordButtonMenu.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.remove('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.add('doboard_task_widget-hidden');
+ }
+ });
+ }
+ const forgotPasswordButtonBlackMenu = document.querySelector('.doboard_task_widget-input-container-login-menu ~ #doboard_task_widget-container-login-forgot-password-form #doboard_task_widget-forgot_password-black');
+ if (forgotPasswordButtonBlackMenu) {
+ forgotPasswordButtonBlackMenu.addEventListener('click', async () => {
+ const forgotPasswordForm = document.getElementById('doboard_task_widget-container-login-forgot-password-form');
+ const loginContainer = document.querySelector('.doboard_task_widget-input-container-login-menu');
+
+ if (forgotPasswordForm) {
+ forgotPasswordForm.classList.add('doboard_task_widget-hidden');
+ }
+ if (loginContainer) {
+ loginContainer.classList.remove('doboard_task_widget-hidden');
+ }
+ });
+ }
+ if (loginButton) {
+ loginButton.addEventListener('click', async () => {
+ const userEmailElement = document.getElementById('doboard_task_widget-login_email');
+ const userPasswordElement = document.getElementById('doboard_task_widget-login_password');
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.add('doboard_task_widget-hidden');
+
+ const userEmail = userEmailElement.value.trim();
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!userEmail) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (!emailRegex.test(userEmail)) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ }
+
+ const userPassword = userPasswordElement.value;
+ if (!userPassword) {
+ userPasswordElement.style.borderColor = 'red';
+ userPasswordElement.focus();
+ userPasswordElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (userPassword.length < 6) {
+ userPasswordElement.style.borderColor = 'red';
+ userPasswordElement.focus();
+ userPasswordElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ }
+
+ try {
+ await loginUser({
+ userEmail: userEmail,
+ userPassword: userPassword
+ })(this.registrationShowMessage);
+ this.setUserMenuData();
+
+ const submitButton = document.getElementById('doboard_task_widget-submit_button');
+ if (submitButton) {
+ submitButton.closest('.doboard_task_widget-field').classList.remove('doboard_task_widget-hidden');
+ }
+
+ } catch (error) {
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');
+ }
+ const sessionIdExists = !!localStorage.getItem('spotfix_session_id');
+ const email = localStorage.getItem('spotfix_email');
+ if (sessionIdExists && email && !email.includes('spotfix_')) {
+ const loginEl= document.querySelector('.doboard_task_widget-login');
+ loginEl?.classList?.add('doboard_task_widget-hidden');
+ } else {
+ document.querySelector('.doboard_task_widget-login-is-invalid').classList.remove('doboard_task_widget-hidden');
+ }
+ })
+ }
+ const passwordToggle = document.getElementById('doboard_task_widget-password-toggle');
+ const passwordInput = document.getElementById('doboard_task_widget-login_password');
+
+ if (passwordToggle && passwordInput) {
+ passwordToggle.addEventListener('click', function() {
+ const isPassword = passwordInput.type === 'password';
+ passwordInput.type = isPassword ? 'text' : 'password';
+ this.classList.toggle('doboard_task_widget-bottom-eye-off-icon');
+ this.classList.toggle('doboard_task_widget-bottom-eye-icon');
+ });
+ }
+ if (restorePasswordButton) {
+ restorePasswordButton.addEventListener('click', async () => {
+ const userEmailElement = document.getElementById('doboard_task_widget-forgot_password_email');
+ const userEmail = userEmailElement.value.trim();
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!userEmail) {
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+ userEmailElement.addEventListener('input', function() {
+ this.style.borderColor = '';
+ });
+ return;
+ } else if (!emailRegex.test(userEmail)) {
+
+ userEmailElement.style.borderColor = 'red';
+ userEmailElement.focus();
+
+ return;
+ }
+
+ try {
+ await forgotPassword(userEmail)(this.registrationShowMessage);
+ } catch (error) {
+ this.registrationShowMessage(error.message, 'error');
+ }
+ })
+ }
+ }
+
/**
* Create widget element
* @return {HTMLElement} widget element
@@ -391,6 +619,7 @@ class CleanTalkWidgetDoboard {
}
// bind creation events
this.bindCreateTaskEvents();
+ this.bindShowLoginFormEvents();
break;
case 'wrap':
await this.getTaskCount();
@@ -540,6 +769,8 @@ class CleanTalkWidgetDoboard {
document.body.appendChild(widgetContainer);
setToggleStatus(this);
checkLogInOutButtonsVisible();
+ this.bindShowLoginFormEvents();
+ this.bindWidgetInputsInteractive();
break;
case 'concrete_issue':
@@ -743,7 +974,7 @@ class CleanTalkWidgetDoboard {
}) || '';
document.querySelector('#doboard_task_widget-user_menu-logout_button')?.addEventListener('click', () => {
- logoutUserDoboard(this.params.projectToken, this.params.accountId).then(() => {this.hide()});
+ logoutUserDoboard(this.params.projectToken);
}) || '';
document.getElementById('addNewTaskButton')?.addEventListener('click', () => {
@@ -768,6 +999,7 @@ class CleanTalkWidgetDoboard {
document.querySelector('#spotfix_back_button')?.addEventListener('click', () => {
this.createWidgetElement(this.type_name)
+ this.bindWidgetInputsInteractive();
}) || '';
return widgetContainer;
@@ -918,6 +1150,7 @@ class CleanTalkWidgetDoboard {
await registerUser(taskDetails)(this.registrationShowMessage);
if ( taskDetails.userPassword ) {
await loginUser(taskDetails)(this.registrationShowMessage);
+ checkLogInOutButtonsVisible();
}
}
@@ -1107,4 +1340,52 @@ class CleanTalkWidgetDoboard {
}
return '';
}
+
+/**
+ * Set user menu data with current user information
+ */
+async setUserMenuData() {
+ const params = this.params;
+
+ // Get user data
+ let userData = null;
+ if (localStorage.getItem('spotfix_session_id')) {
+ try {
+ userData = await getUserDetails(params);
+ } catch (error) {
+ console.error('Error fetching user details:', error);
+ }
+ }
+
+ // Update user menu header
+ const userNameElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 16px"]');
+ const emailElement = document.querySelector('.doboard_task_widget-user_menu-header span[style*="font-size: 12px"]');
+ const avatarElement = document.querySelector('.doboard_task_widget-user_menu-header-avatar');
+
+ if (userNameElement) {
+ if (userData && userData.name) {
+ userNameElement.innerText = userData.name;
+ } else {
+ userNameElement.innerText = 'Guest';
+ }
+ }
+
+ if (emailElement) {
+ if (userData && userData.email) {
+ emailElement.innerText = userData.email;
+ } else {
+ const email = localStorage.getItem('spotfix_email') || '';
+ emailElement.innerText = email.includes('spotfix_') ? '' : email;
+ }
+ }
+
+ if (avatarElement) {
+ if (userData && userData.avatar && userData.avatar.s) {
+ avatarElement.src = userData.avatar.s;
+ } else {
+ // Reset to default avatar or remove src
+ avatarElement.src = '';
+ }
+ }
+}
}
diff --git a/styles/doboard-widget.css b/styles/doboard-widget.css
index 0646efc..9319441 100644
--- a/styles/doboard-widget.css
+++ b/styles/doboard-widget.css
@@ -159,7 +159,8 @@
align-items: center;
border-bottom: 1px #EBF0F4 solid;
padding: 0 16px;
- height: 65px;
+ height: 40px;
+ margin-top: 10px;
}
.doboard_task_widget-content {
@@ -268,7 +269,7 @@
position: relative;
margin-bottom: 24px;
}
-.doboard_task_widget-input-container.hidden {
+.doboard_task_widget-input-container.hidden, .doboard_task_widget-hidden {
display: none;
}
@@ -345,16 +346,16 @@
.doboard_task_widget-login .doboard_task_widget-input-container:last-child {
margin-bottom: 0;
}
-.doboard_task_widget-login span {
+.doboard_task_widget-login .doboard_task_widget-login-icon {
display: block;
position: relative;
padding-right: 24px;
cursor: pointer;
}
-.doboard_task_widget-login.active span {
+.doboard_task_widget-login.active .doboard_task_widget-login-icon {
margin-bottom: 24px;
}
-.doboard_task_widget-login span::after {
+.doboard_task_widget-login .doboard_task_widget-login-icon::after {
position: absolute;
top: 0;
right: 4px;
@@ -369,7 +370,7 @@
border-left: none;
transition: all 0.2s ease-in-out;
}
-.doboard_task_widget-login.active span::after {
+.doboard_task_widget-login.active .doboard_task_widget-login-icon::after {
transform: rotate(-135deg);
top: 7px;
}
@@ -378,7 +379,7 @@
background: #F9FBFD;
}
.doboard_task_widget-submit_button {
- height: 48px;
+ min-height: 48px;
width: 100%;
max-width: 400px;
margin-bottom: 10px;
@@ -405,6 +406,39 @@
cursor: wait;
}
+.doboard_task_widget-login-buttons-wrapper {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 10px;
+}
+
+.doboard_task_widget-login-buttons-wrapper .doboard_task_widget-submit_button {
+ margin-bottom: 0;
+ width: auto;
+ min-height: 32px;
+ font-size: 14px;
+ padding: 4px 12px;
+}
+
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page,
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black {
+ flex: 1;
+ background: #FFFFFF;
+ border: 1px solid #22A475;
+ color: #22A475;
+}
+
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-on_phantom_login_page:hover,
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-forgot_password-black:hover {
+ background: #f0fdf4;
+ color: #1C7857;
+}
+
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-login_button,
+.doboard_task_widget-login-buttons-wrapper #doboard_task_widget-restore_password_button {
+ flex: 2;
+}
+
.doboard_task_widget-issue-title {
max-width: 200px;
white-space: nowrap;
@@ -1274,4 +1308,55 @@ input:checked + .slider:before {
color: #707A83;
cursor: pointer;
}
+.doboard_task_widget-show_login_form, .doboard_task_widget-on_phantom_login_page, .doboard_task_widget-forgot_password {
+ display: inline-block;
+ cursor: pointer;
+ color: #2F68B7;
+ margin-bottom: 0;
+}
+.doboard_task_widget-forgot_password {
+ margin-bottom: 20px;
+}
+
+.doboard_task_widget-login-is-invalid {
+ color: red;
+}
+
+.doboard_task_widget-input-container-login-menu,
+.doboard_task_widget-forgot_password_form-menu{
+ margin: 20px;
+}
+
+
+.doboard_task_widget-bottom-eye-icon {
+ position: absolute;
+ right: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 20px;
+ height: 20px;
+ background: #fff url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMjAgMjAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDIwIDIwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBkPSJNMTAsMTcuNGMtNi4yLDAtOS43LTYuOC05LjgtNy4xYy0wLjEtMC4yLTAuMS0wLjUsMC0wLjdDMC4zLDkuNCwzLjgsMi42LDEwLDIuNmM2LjIsMCw5LjcsNi44LDkuOCw3LjENCgljMC4xLDAuMiwwLjEsMC41LDAsMC43QzE5LjcsMTAuNiwxNi4yLDE3LjQsMTAsMTcuNHogTTEuNywxMGMwLjgsMS4zLDMuNyw1LjksOC4zLDUuOWM0LjYsMCw3LjYtNC42LDguMy01LjkNCgljLTAuOC0xLjMtMy43LTUuOS04LjMtNS45QzUuNCw0LjEsMi40LDguNywxLjcsMTB6IE0xMCwxMy4zYy0xLjgsMC0zLjMtMS41LTMuMy0zLjNTOC4yLDYuOCwxMCw2LjhzMy4zLDEuNSwzLjMsMy4zDQoJUzExLjgsMTMuMywxMCwxMy4zeiBNMTAsOC4zQzksOC4zLDguMyw5LDguMywxMFM5LDExLjgsMTAsMTEuOHMxLjgtMC44LDEuOC0xLjhTMTEsOC4zLDEwLDguM3oiLz4NCjwvc3ZnPg0K) no-repeat center center;
+ background-size: 16px 16px;
+ cursor: pointer;
+ border-radius: 50%;
+ transition: all 0.2s ease;
+ z-index: 10;
+}
+
+.doboard_task_widget-bottom-eye-off-icon {
+ position: absolute;
+ right: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 20px;
+ height: 20px;
+ background: #fff url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDIwIDIwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyMCAyMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE2LjgsMTMuMmMwLjEsMC4xLDAuMywwLjIsMC41LDAuMmMwLDAsMCwwLDAsMGMwLjIsMCwwLjQtMC4xLDAuNS0wLjNjMC43LTAuOSwxLjQtMS44LDEuOS0yLjgNCgljMC4xLTAuMiwwLjEtMC41LDAtMC43Yy0wLjEtMC4zLTMuNi03LjEtOS44LTcuMWMwLDAsMCwwLDAsMGMtMC42LDAtMS4zLDAuMS0xLjksMC4yQzcuOCwyLjksNy42LDMuMSw3LjUsMy4zczAsMC41LDAuMiwwLjcNCglMMTYuOCwxMy4yeiBNMTAsNC4xYzQuNiwwLDcuNiw0LjYsOC4zLDUuOWMtMC4zLDAuNS0wLjYsMS0xLDEuNUw5LjksNC4xQzkuOSw0LjEsMTAsNC4xLDEwLDQuMXogTTE5LjcsMTguNmwtNC4yLTQuMkw1LjYsNC41DQoJYzAsMCwwLDAsMCwwTDEuNCwwLjNDMS4xLDAsMC42LDAsMC4zLDAuM1MwLDEuMSwwLjMsMS40TDMuOSw1QzIuNCw2LjMsMS4xLDcuOSwwLjIsOS42Yy0wLjEsMC4yLTAuMSwwLjUsMCwwLjcNCgljMC4xLDAuMywzLjYsNy4xLDkuOSw3LjFjMS43LDAsMy40LTAuNSw0LjktMS41bDMuOCwzLjhjMC4xLDAuMSwwLjMsMC4yLDAuNSwwLjJzMC40LTAuMSwwLjUtMC4yQzIwLDE5LjQsMjAsMTguOSwxOS43LDE4LjZ6DQoJIE04LjMsOS40bDIuMywyLjNjLTAuMiwwLjEtMC40LDAuMS0wLjYsMC4xYy0wLjIsMC0wLjUsMC0wLjctMC4xYy0wLjItMC4xLTAuNC0wLjItMC42LTAuNGMtMC4yLTAuMi0wLjMtMC40LTAuNC0wLjYNCgljLTAuMS0wLjItMC4xLTAuNS0wLjEtMC43QzguMiw5LjgsOC4yLDkuNiw4LjMsOS40eiBNMTAsMTUuOWMtNC42LDAtNy42LTQuNi04LjMtNS45YzAuOS0xLjUsMi0yLjgsMy4zLTMuOWwyLjIsMi4yDQoJQzcuMSw4LjQsNyw4LjYsNyw4LjdDNi44LDkuMSw2LjcsOS42LDYuNywxMGMwLDAuNCwwLjEsMC45LDAuMiwxLjNjMC4yLDAuNCwwLjQsMC44LDAuNywxLjFjMC4zLDAuMywwLjcsMC42LDEuMSwwLjcNCgljMC40LDAuMiwwLjgsMC4yLDEuMywwLjJjMC40LDAsMC45LTAuMSwxLjMtMC4zYzAuMi0wLjEsMC4zLTAuMiwwLjUtMC4zbDIuMSwyLjFDMTIuNiwxNS41LDExLjMsMTUuOSwxMCwxNS45eiIvPg0KPC9zdmc+DQo=) no-repeat center center;
+ background-size: 16px 16px;
+ cursor: pointer;
+ border-radius: 50%;
+ transition: all 0.2s ease;
+ opacity: 0.5;
+ z-index: 10;
+
+}