1app.component("onboardingWizard", { 2 bindings: { 3 provider: '<?' 4 }, 5 templateUrl: "/app/components/home/onboarding.wizard.html", 6 7 controller: function ($uibModal, $log, $localstorage, AuthService, $rootScope, $timeout, $location) { 8 9 10 let self = this; 11 12 self.onboarder_dismissed = false; 13 self.onboarding_actions = []; 14 self.onboarding_progress = 0; 15 self.onboarding_steps_complete = 0; 16 self.onboarding_max = 0; 17 18 let onboarding_var = AuthService.User.role + '_onboarding'; 19 let onboarding_id = AuthService.User.orgid + '_orgid'; 20 let onboarding_actions = onboarding_var + '_actions'; 21 22 23 let provider_onboarding_actions = [ 24 {id: 1, title: "Upload a logo", complete: false, href: "/uorg/uploads"}, 25 // {id: 1, title: "Run the tour", complete: false}, 26 // {id: 2, title: "Watch the product video", complete: false}, 27 {id: 2, title: "Complete a Trade Services Hub profile", complete: false, action: true}, 28 {id: 3, title: "Complete company address/EORI", href: "/uorg/registrations", complete: false}, 29 {id: 4, title: "Create a client workspace", complete: false, action: true }, 30 {id: 5, title: "Invite colleagues", href: "/uorg/contacts", complete: false}, 31 ]; 32 33 let trader_onboarding_actions = [ 34 {id: 1, title: "Run the tour", complete: false}, 35 {id: 2, title: "Watch the product video", complete: false}, 36 {id: 4, title: "Invite colleagues", complete: false}, 37 {id: 5, title: "Complete company details", complete: false}, 38 {id: 6, title: "Upload a logo", complete: false} 39 ]; 40 41 42 self.$onInit = function () { 43 44 let onboarding_history = $localstorage.getObject(onboarding_var); 45 46 if (!(onboarding_history && onboarding_history.actions) || 47 !(onboarding_id == onboarding_history.id)) // todo add version check too 48 { 49 50 let config; 51 if (AuthService.User.role == 'provider' && [6,7,8].includes(AuthService.User.base_plan_id)) { 52 config = angular.copy({ id: onboarding_id, version: 'p1.01', dismissed: self.onboarder_dismissed, actions: provider_onboarding_actions} ); 53 } else if ([1,2,3].includes(AuthService.User.base_plan_id)) { 54 config = angular.copy({ id: onboarding_id, version: 't0.01', dismissed: self.onboarder_dismissed, actions: trader_onboarding_actions} ); 55 } else { 56 return 57 } 58 59 $localstorage.setObject(onboarding_var, config); 60 self.onboarding_actions = config.actions; 61 62 } else { 63 64 self.onboarding_actions = onboarding_history.actions; 65 self.onboarder_dismissed = onboarding_history.dismissed; 66 // check to see if it where it is different, add the new or changed titles 67 } 68 69 updateWizard(); 70 71 } 72 73 74 let updateWizard = function () { 75 const tempFilterData = _.filter(self.onboarding_actions, { complete: true }); 76 self.onboarding_steps_complete = (tempFilterData && tempFilterData.length) || 0; 77 self.onboarding_max = self.onboarding_actions.length; 78 self.onboarding_progress = Math.floor(self.onboarding_steps_complete / self.onboarding_actions.length * 100 + 1); 79 80 $rootScope.$emit('watchOnBoardingProgress'); 81 } 82 83 84 $rootScope.$on('onboarding-action', (event, data) => { 85 86 let index = self.onboarding_actions.findIndex((action) => { 87 return (action.id == data) 88 }) 89 90 if (index > -1) { 91 92 self.onboarding_actions[index].complete = true; 93 updateWizard(); 94 } 95 96 let update_local = $localstorage.getObject(onboarding_var); 97 update_local.actions = self.onboarding_actions; 98 $localstorage.setObject(onboarding_var, update_local); 99 //console.log("receiving onboard completion event") 100 $rootScope.$emit('watchOnBoardingProgress'); 101 }); 102 103 104 self.dismissOnboarder = function (dismissed = true) { 105 106 let onboarding_history = $localstorage.getObject(onboarding_var); 107 onboarding_history.dismissed = dismissed; 108 // am not why I need the scope apply! (normally only used if outside angular) 109 $localstorage.setObject(onboarding_var, onboarding_history); 110 111 self.onboarder_dismissed = dismissed; 112 113 } 114 115 self.reopen_onboarder = function () { 116 self.dismissOnboarder(false); 117 } 118 119 $rootScope.$on("reopenOnboardingAction", self.reopen_onboarder); 120 121 self.launchAction = function (id) { 122 123 switch (id) { 124 case 4: 125 openAddClient(); 126 break 127 case 2: 128 openTshProfile(); 129 break 130 default: 131 const action = provider_onboarding_actions.find((el)=>{return el.id == id }); 132 $location.path(action.href || '#'); 133 return 134 } 135 } 136 137 let openAddClient = function () { 138 139 $location.path('/home'); 140 141 $timeout(()=>{ 142 $rootScope.$emit('open-add-client',{}); 143 },1000) 144 145 146 147 } 148 149 150 let openTshProfile = function () { 151 var modalInstance = $uibModal.open({ 152 animation: true, 153 component: 'tshProfile' 154 // resolve: { 155 // items: function () { 156 // return $ctrl.items; 157 // } 158 // } 159 }); 160 161 modalInstance.result.then(function (selectedItem) { 162 self.selected = selectedItem; 163 }, function () { 164 $log.info('modal-component dismissed at: ' + new Date()); 165 }); 166 }; 167 168 169 } 170}); 171 172 173app.component("tshProfile", { 174 bindings: { 175 resolve: '<', 176 close: '&',
177 dismiss: '&' 178 }, 179 templateUrl: "tshOnboardQuestions.html", 180 181 controller: function ( 182 $rootScope, 183 $localstorage, 184 $timeout, 185 $http, 186 orgServices, 187 AuthService, 188 TradeModelService) { 189 190 191 var self = this; 192 193 $http.get('/data/onboarding.php').then((results) => { 194 195 let user_type; 196 if ([6].includes(AuthService.User.base_plan_id)) { 197 user_type = "freight"; 198 } else if ([7,8].includes(AuthService.User.base_plan_id)) { 199 user_type = "customs_agent"; 200 } 201 const found = results.data[0].find((elem) => { return elem.user_type === user_type; }); 202 if (found) self.onboarding_questions = found.questions; 203 204 }); 205 206 207 var currentTab = 0; // Current tab is set to be the first tab (0) 208 self.currentOrgData = null; 209 210 self.$onInit = function () { 211 212 213 $timeout(() => { 214 showTab(currentTab); // Display the current tab 215 216 self.currentUser = AuthService.User; 217 orgServices.getMyOrganisation() 218 .then((result) => { 219 self.currentOrgData = result; 220 221 const previously_completed = _.get(result, "extra_data.tsh_profile", []); 222 if (previously_completed.length > 0) { 223 // self.onboarding_questions = previously_completed; 224 } 225 226 if (self.onboarding_questions) { 227 self.onboarding_questions = self.onboarding_questions.map(function (item) { 228 // if (item.type === 'select') { 229 // item.selectedValue = item.options.length > 0 ? item.options[0].value : ''; 230 // } 231 if (typeof item.options === 'string') { 232 if (item.options === 'regions') { 233 item.options = self.countries; 234 } else if (item.options === 'ukports') { 235 item.options = self.ukports; 236 } 237 } 238 previously_completed.forEach((pitem) => { 239 if (pitem.name === item.name) { 240 if (pitem.selectedValue) item.selectedValue = pitem.selectedValue; 241 if (pitem.selectedOptions) item.selectedOptions = pitem.selectedOptions; 242 if (pitem.other_options) item.other_options = pitem.other_options; 243 } 244 }) 245 return item; 246 }); 247 } 248 249 }) 250 .catch((error) => { 251 console.error("Problem getting provider details in onboarding modal " + JSON.stringify(error)); 252 }); 253 254 },500) 255 256 } 257 self.ok = async function () { 258 259 // save to org data of my company 260 // capture all the questions and save on the org data 261 // so it is saved under extra_data.tsh_profile = {} an object 262 263 if (self.currentOrgData && self.currentOrgData.extra_data) { 264 265 self.onboarding_questions.forEach((question)=>{ 266 if(question.options) 267 delete question.options 268 delete question.label 269 delete question.type 270 }) 271 272 self.currentOrgData.extra_data.tsh_profile = self.onboarding_questions; 273 274 275 await orgServices.updateUOrg(self.currentOrgData).then(function(resp) { 276 if (resp && resp.status === 200 && resp.data && resp.data.success) { 277 } 278 }).catch(function(err) { 279 console.log('Getting error while updating organisation data for onboarding wizard', err) 280 }); 281 } 282 283 $rootScope.$emit('onboarding-action', 2); 284 285 // todo -- add a update to the onboarding wizard local storage to set this item complete 286 // 287 288 self.close({$value: 'ok'}); 289 }; 290 291 self.cancel = async function () { 292 293 if (self.currentOrgData && self.currentOrgData.extra_data) { 294 295 self.onboarding_questions.forEach((question)=>{ 296 if(question.options) 297 delete question.options 298 delete question.label 299 delete question.type 300 }) 301 302 self.currentOrgData.extra_data.tsh_profile = self.onboarding_questions; 303 304 await orgServices.updateUOrg(self.currentOrgData); 305 } 306 307 self.dismiss({$value: 'cancel'}); 308 309 }; 310 311 self.countries = TradeModelService.ordered_countries_list.map((c) => { 312 return {value: c.alpha_2, text: c.name} 313 }); 314 self.ukports = TradeModelService.CDS_locations_array.map((loc) => { 315 return {value: loc.code, text: loc.code+" - "+loc.desc} 316 }); 317 318 function showTab(n) { 319 // This function will display the specified tab of the form ... 320 var x = document.getElementsByClassName("tab"); 321 322 x[n].style.display = "block"; 323 // ... and fix the Previous/Next buttons: 324 if (n == 0) { 325 document.getElementById("prevBtn").style.display = "none"; 326 } else { 327 document.getElementById("prevBtn").style.display = "inline"; 328 } 329 if (n == (x.length - 1)) { 330 document.getElementById("nextBtn").innerHTML = "Submit"; 331 } else { 332 document.getElementById("nextBtn").innerHTML = "Next"; 333 } 334 // ... and run a function that displays the correct step indicator: 335 // fixStepIndicator(n) 336 } 337 338 self.nextPrev = function (n) { 339 // This function will figure out which tab to display 340 var x = document.getElementsByClassName("tab"); 341 // Exit the function if any field in the current tab is invali
341d: 342 if (n == 1 && !validateForm()) return false; 343 // Hide the current tab: 344 x[currentTab].style.display = "none"; 345 // Increase or decrease the current tab by 1: 346 currentTab = currentTab + n; 347 // if you have reached the end of the form... : 348 if (currentTab >= x.length) { 349 //...the form gets submitted: 350 //document.getElementById("regForm").submit(); 351 // set next steps 352 353 return false; 354 } 355 // Otherwise, display the correct tab: 356 showTab(currentTab); 357 } 358 359 let validateForm = function () { 360 361 return true; // disabled 362 363 // This function deals with validation of the form fields 364 var x, y, i, valid = true; 365 x = document.getElementsByClassName("tab"); 366 y = x[currentTab].getElementsByTagName("select"); 367 // A loop that checks every input field in the current tab: 368 for (i = 0; i < y.length; i++) { 369 // If a field is empty... 370 if (y[i].value == "") { 371 // add an "invalid" class to the field: 372 y[i].className += " invalid"; 373 // and set the current valid status to false: 374 valid = false; 375 } 376 } 377 // If the valid status is true, mark the step as finished and valid: 378 if (valid) { 379 document.getElementsByClassName("step")[currentTab].className += " finish"; 380 } 381 return valid; // return the valid status 382 } 383 384 self.toggle = function(question) { 385 if (!question.all_selected) { 386 question.selectedValue = question.options.map((o) => { 387 return o.value 388 }); 389 question.all_selected = true; 390 } else { 391 question.selectedValue = undefined; 392 question.all_selected = false; 393 } 394 } 395 396 self.addToSelected = function(question, option) { 397 if (!question.selectedOptions) question.selectedOptions = []; 398 // don't add if already existing 399 question.selectedOptions.push(option); 400 } 401 402 self.deleteFromSelected = function(question, idx) { 403 question.selectedOptions.splice(idx, 1); 404 } 405 406 self.addOther = function(question) { 407 if (!question.other_options) question.other_options = []; 408 question.other_options.push({text: "", value: ""}); 409 } 410 411 self.updateOther = function(question, idx) { 412 const user_input = question.other_options[idx].text; 413 question.other_options[idx] = {text: user_input, value: user_input, cardtext: user_input}; 414 } 415 416 self.deleteOther = function(question, idx) { 417 question.other_options.splice(idx, 1); 418 } 419 420 // let fixStepIndicator = function (n) { 421 422 // // This function removes the "active" class of all steps... 423 // var i, x = document.getElementsByClassName("#RegForm.step"); 424 // for (i = 0; i < x.length; i++) { 425 // x[i].className = x[i].className.replace(" active", ""); 426 // } 427 // //... and adds the "active" class to the current step: 428 // x[n].className += " active"; 429 // } 430 431 432 } 433}); 434
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.