1import {globalProgress, L} from '../../ui/utils.js' 2import {firemsg} from '../../ui/firemsg.js' 3import {Modal} from '../../ui/modal.js' 4 5/** @type {HTMLFormElement|null} form */ 6const form = document.getElementById('recommender-interest-control-form') 7if (form) { 8 /** @type {HTMLFormElement|null} fromLoader */ 9 const formLoader = form.querySelector('.as-loader') 10 /** @type {HTMLFormElement|null} formNoLoader */ 11 const formNoLoader = form.querySelector('.as-noloader') 12 /** @type {HTMLFormElement|null} formArea */ 13 const formArea = form.querySelector('.data') 14 /** @type {HTMLFormElement|null} formArea */ 15 const subDescription = form.querySelector('.sub-description') 16 17 /** 18 * @param {string|null} [recommenderData] json 19 * @returns {Promise<void>} 20 */ 21 const loadData = (recommenderData) => { 22 formLoader.style.display = 'block' 23 formNoLoader.style.display = 'none' 24 return fetch('/interest/list/decode-from-item', { 25 method: 'POST', 26 body: recommenderData, 27 headers: {'Content-Type': 'application/json'} 28 }) 29 .then((response) => { 30 response.json().then(data => { 31 if(data.html) { 32 formArea.innerHTML = data.html 33 } 34 if(!data.interests || !data.interests.length) { 35 firemsg(L('РеÑÑÑÑ Ð½Ðµ ÑвлÑеÑÑÑ Ð¿ÐµÑÑоналÑной ÑекомендаÑией', 'The resource is not a personal recommendation')) 36 Modal.close(null) 37 } 38 }) 39 }) 40 .catch(r => { 41 formArea.innerHTML = r.statusText || 'Error '+r.status 42 }) 43 .finally(() => { 44 formLoader.style.display = 'none' 45 formNoLoader.style.display = 'block' 46 }) 47 } 48 document.body.addEventListener('click', e => { 49 const button = e.target.closest('[data-interests-control]') 50 if (!button) return 51 formArea.innerHTML = '' 52 const resource = button.closest('.as-resource') 53 button.remove() 54 const recommenderDataInput = resource.querySelector('.as-resource-recommender-data'); 55 if(!recommenderDataInput || !recommenderDataInput.value || recommenderDataInput.value.indexOf('"interests":[]') != -1) { 56 firemsg(L('РеÑÑÑÑ Ð½Ðµ ÑвлÑеÑÑÑ Ð¿ÐµÑÑоналÑной ÑекомендаÑией', 'The resource is not a personal recommendation')) 57 return 58 } 59 loadData(recommenderDataInput.value) 60 61 Modal.open(async () => { 62 return form 63 }, null) 64 }) 65 document.body.addEventListener('click', e => { 66 const button = e.target.closest('[data-interest-adjust]') 67 if (!button) return 68 form.querySelectorAll('.interest-control-item-actions-btn').forEach(v => { v.disabled = true }) 69 const item = button.closest('.resource-recommender-interest-control-item') 70 const weightEl = item.querySelector('.interest-control-item-weight') 71 const valueEl = item.querySelector('.interest-control-item-weight-value') 72 const interest = JSON.parse(item.dataset.interest); 73 interest.w = parseFloat(valueEl.innerHTML)/100.0; 74 75 fetch('/interest/adjust/'+button.dataset.interestAdjust, { 76 method: 'POST', 77 body: JSON.stringify(interest), 78 headers: {'Content-Type': 'application/json'} 79 }) 80 .then((response) => { 81 form.querySelectorAll('.interest-control-item-actions-btn').forEach(v => { v.disabled = false }) 82 response.json().then(data => { 83 if(data.interest) { 84 if(subDescription) { 85 subDescription.style.display = 'block' 86 } 87 88 valueEl.innerHTML = (data.interest.w * 100.0).toFixed(2) 89 if(data.interest.w > 0.5) { 90 weightEl.classList.add('interest-control-item-we
90ight-recommended') 91 } else { 92 weightEl.classList.remove('interest-control-item-weight-recommended') 93 } 94 form.querySelector('.interest-control-summary').style.display = 'none' 95 item.dataset.interest = JSON.stringify(data.interest) 96 } 97 }) 98 }) 99 100 }) 101} 102 103 104/** 105 * @event CustomEvent#onboarding.recommender.select 106 */ 107/** @type {HTMLFormElement|null} onboardingForm */ 108const onboardingForm = document.getElementById('recommender-interest-onboarding-form') 109if(onboardingForm) { 110 /** @type {HTMLFormElement|null} fromLoader */ 111 const formLoader = onboardingForm.querySelector('.as-loader') 112 /** @type {HTMLFormElement|null} formArea */ 113 const formArea = onboardingForm.querySelector('.data') 114 115 /** 116 * @returns {Promise<void>} 117 */ 118 const loadData = () => { 119 formLoader.style.display = 'block' 120 return fetch('/interest/onboarding/load?old='+window.xgm.onboarding['recommender.old']) 121 .then((response) => { 122 response.json().then(data => { 123 if(data.html) { 124 formArea.innerHTML = data.html 125 } 126 Modal.open(async () => { 127 return onboardingForm 128 }, null) 129 }) 130 }) 131 .catch(r => { 132 formArea.innerHTML = r.statusText || 'Error '+r.status 133 }) 134 .finally(() => { 135 formLoader.style.display = 'none' 136 }) 137 } 138 139 if(window.xgm.onboarding['recommender'] == 'show_window') { 140 loadData() 141 } 142 143 document.body.addEventListener('click', e => { 144 const button = e.target.closest('[data-interest-helper]') 145 if (!button) return 146 e.preventDefault() 147 loadData() 148 }) 149 150 document.body.addEventListener('click', e => { 151 const button = e.target.closest('[data-interest-helper-select]') 152 if (!button) return 153 e.preventDefault() 154 let target = button.dataset.interestHelperSelect 155 button.dispatchEvent(new CustomEvent("onboarding.recommender.select", { bubbles: true, detail: target })) 156 fetch('/interest/onboarding/save/'+target, { 157 method: 'POST' 158 }).then(() => { 159 Modal.close(null) 160 if(target != 'later') { 161 firemsg(L('СпаÑибо!', 'Thank you!')) 162 } 163 if(target != 'nochange' && target != 'later') { 164 setTimeout(() => document.location.reload(), 750) 165 } 166 }) 167 }) 168}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.