1var app = new Vue({ 2 mixins: [mainMixin], 3 el: "#app", 4 data: { 5 showStudentNames:true, 6 mode_shown: true, 7 mode_hidden: true, 8 mode_stellar: true, 9 audio_off: true, 10 audio_target: true, 11 audio_definition: true, 12 infoWasShown: false, 13 selectedTrackerStudent: "", 14 selectedTrackerClass: "", 15 selectedTrackerSet: "", 16 manageQuizzesFilter: "", 17 manageSetsFilter: "", 18 trackerSetsShown: false, 19 assignmentEditId: "", 20 checkAll: false, 21 customGridData: [], 22 termsTable: null, 23 trackerStudentsFilter: "", 24 trackerClassesFilter: "", 25 trackerSetsFilter: "", 26 sharesWithMe: [], 27 trackerview: "students", 28 importSetId: "", 29 deletingSet: false, 30 userSets: [], 31 toImport: "", 32 terms: [], 33 setName: "", 34 setLangs: { 35 definition: "en", 36 term: "en", 37 }, 38 editId: "", 39 lang_filter: [ 40 "ar", 41 "zh-CN", 42 "zh-pi", 43 "zh-TW", 44 "de", 45 "fr", 46 "it", 47 "ja", 48 "ko", 49 "ru", 50 "es", 51 "th", 52 "tr", 53 "en", 54 "vi", 55 "pt", 56 ], 57 savingSet: false, 58 voices: [ 59 "Arabic Male", 60 "Australian Female", 61 "Chinese Female", 62 "Deutsch Female", 63 "French Female", 64 "Italian Female", 65 "Japanese Female", 66 "Korean Female", 67 "Russian Female", 68 "Spanish Female", 69 "Thai Female", 70 "Turkish Female", 71 "UK English Female", 72 "UK English Male", 73 "US English Female", 74 "Vietnamese Male", 75 ], 76 modes: { 77 full: "Full Words", 78 fandl: "Hidden Letters", 79 star: "Stellar Speller", 80 }, 81 assignment: { 82 instructions: 83 "(Customize instructions here!) LingoLab: One point is deducted for each mistake made. If an answering word that you select is incorrect, the correct word is then shown to you by flashing yellow. You should click it to continue answering the question. Stellar Speller: Spell out the target word or phrase. 1 point is deducted for each mistake.", 84 show_score: false, 85 shuffle_order: false, 86 ppq: 3, 87 classes: "", 88 title: "", 89 set: {}, 90 mode: "full", 91 tts: "off", 92 tts_voice: "US English Female", 93 elements: { 94 definition: true, 95 image: true, 96 }, 97 }, 98 customSetId: "", 99 defaultSets: [], 100 screen: "", 101 subscreen: "default_sets", 102 setType: "sentence", 103 languages: languages, 104 user: user, 105 assignments: assignments, 106 }, 107 computed: { 108 uniqueSharedSets: function () { 109 return this.getSharedSets().filter((obj, pos, arr) => { 110 return arr.map((mapObj) => mapObj["name"]).indexOf(obj["name"]) === pos; 111 }); 112 }, 113 }, 114 watch: { 115 infoWasShown: function () { 116 if (this.infoWasShown) { 117 localStorage.setItem("infoWasShown", "true"); 118 } 119 }, 120 trackerview: function () { 121 this.resetTracker(); 122 }, 123 trackerStudentsFilter: function () { 124 Vue.nextTick(function () { 125 $(".progress-tracker-students").trigger("update"); 126 }); 127 }, 128 screen: function () { 129 var vm = this; 130 131 if (this.screen == "create_set") { 132 Vue.nextTick(function () { 133 var data = []; 134 for (var i = 0; i < 20; i++) { 135 data.push(["", "", ""]); 136 } 137 138 if (vm.customGridData.length) { 139 data = vm.customGridData; 140 vm.customGridData = []; 141 } 142 var container = document.getElementById("importTermsTable"); 143 144 vm.termsTable = new Handsontable(container, { 145 minSpareRows: 5, 146 allowEmpty: false, 147 data: data, 148 colWidths: [240, 240, 240], 149 contextMenu: ["remove_row"], 150 rowHeaders: false, 151 colHeaders: ["Answer", "Question", "Image URL (Optional)"], 152 filters: false, 153 dropdownMenu: false, 154 licenseKey: "non-commercial-and-evaluation", 155 columnSorting: true, 156 }); 157 }); 158 } 159 }, 160 "assignment.ppq": function () { 161 if (this.assignment.ppq < 1) { 162 this.assignment.ppq = 1; 163 } 164 if (this.assignment.ppq > 100) { 165 this.assignment.ppq = 100; 166 } 167 }, 168 "assignment.set": function () { 169 if (!this.hasImages(this.assignment.set)) { 170 this.assignment.elements.image = false;
171 } else { 172 this.assignment.elements.image = true; 173 } 174 }, 175 }, 176 methods: { 177 downloadSetsTable(idx, filename) { 178 $("#progress-table-" + idx).table2csv("download", { 179 filename: filename + ".csv", 180 }); 181 }, 182 downloadStudentsTable() { 183 $("#students-table").table2csv("download", { 184 filename: this.trackerview + ".csv", 185 }); 186 }, 187 sort_tables() { 188 if (this.screen == "manage") { 189 $(".manage-tests").tablesorter({ 190 theme: "bootstrap", 191 sortList: [[0, 0]], 192 }); 193 } 194 if (this.screen == "manage_sets") { 195 $(".manage-sets").tablesorter({ 196 theme: "bootstrap", 197 sortList: [[2, 1]], 198 }); 199 } 200 }, 201 get_url_param: function (name, url) { 202 if (!url) url = window.location.href; 203 name = name.replace(/[\[\]]/g, "\\$&"); 204 var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 205 results = regex.exec(url); 206 if (!results) return null; 207 if (!results[2]) return ""; 208 return decodeURIComponent(results[2].replace(/\+/g, " ")); 209 }, 210 duplicateAssignment: function (assignment_id) { 211 var vm = this; 212 axios 213 .post("/lingolab_online.class.php", { 214 action: "duplicateAssignment", 215 data: { 216 assignment_id: assignment_id, 217 }, 218 }) 219 .then(function (response) { 220 if (response.data.result == "success") { 221 Swal.fire({ 222 reverseButtons: true, 223 title: "Success", 224 html: 225 "Assignment copied to:<br/><a target='_blank' href='https://lingolab.online/submit.php?id=" + 226 response.data.id + 227 "'>https://lingolab.online/submit.php?id=" + 228 response.data.id + 229 "</a>", 230 type: "success", 231 }); 232 vm.assignments = response.data.assignments; 233 vm.screen = "manage"; 234 } else { 235 Swal.fire({ 236 reverseButtons: true, 237 title: "Error", 238 text: response.data.message, 239 type: "error", 240 }); 241 } 242 }) 243 .catch(function (error) { 244 console.error(error); 245 }); 246 }, 247 createNewAssignment: function () { 248 this.assignmentEditId = ""; 249 this.assignment = { 250 instructions: 251 "(Customize instructions here!) LingoLab: One point is deducted for each mistake made. If an answering word that you select is incorrect, the correct word is then shown to you by flashing yellow. You should click it to continue answering the question. Stellar Speller: Spell out the target word or phrase. 1 point is deducted for each mistake.", 252 show_score: false, 253 shuffle_order: false, 254 ppq: 3, 255 classes: "", 256 title: "", 257 set: {}, 258 mode: "full", 259 tts: "off", 260 tts_voice: "US English Female", 261 elements: { 262 definition: true, 263 image: true, 264 }, 265 }; 266 this.screen = "create"; 267 }, 268 editAssignment: function (assignment) { 269 this.assignmentEditId = assignment.id; 270 this.assignment = assignment.json; 271 this.screen = "create"; 272 }, 273 createNewSet: function () { 274 this.reset(); 275 this.screen = "create_set"; 276 }, 277 resetChecked: function () { 278 var vm = this; 279 Swal.fire({ 280 title: 281 "Are you sure you wish to reset the Current Total for " + 282 vm.getChecked().length + 283 " checked students?", 284 showCancelButton: true, 285 reverseButtons: true, 286 }).then((result) => { 287 if (result.value) { 288 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 289 axios 290 .post("/lingolab_online.class.php", { 291 action: "resetChecked", 292 data: { 293 subs: vm.getChecked(), 294 }, 295 }) 296 .then(function (response) { 297 $("#checkAll").prop("checked", false); 298 $(".share-check").prop("checked", false); 299 if (response.data.result == "success") { 300 vm.loadTracker(); 301 } else { 302 Swal.fire({ 303 reverseButtons: true, 304 title: "Error", 305 text: response.data.message, 306 type: "error", 307 }); 308 } 309 }) 310 .catch(function (error) { 311 console.error(error); 312 }); 313 } 314 }); 315 }, 316 removeChecked: function () { 317 var vm = this; 318 Swal.fire({ 319 title: 320 "Are you sure you wish to remove " + 321 vm.getChecked().length + 322 " checked students from your tracker?", 323 showCancelButton: true, 324 reverseButtons: true, 325 }).then((result) => { 326 if (result.value) { 327 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 328 axios 329 .post("/lingolab_online.class.php", { 330 action: "removeChecked", 331 data: { 332 subs: vm.getChecked(), 333 }, 334 }) 335 .then(function (response) { 336 $("#checkAll").prop("checked", false); 337 $(".share-check").prop("checked", false); 338 if (response.data.result == "success") { 339 vm.loadTracker(); 340 } else { 341 Swal.fire({ 342 reverseButtons: true, 343 title: "Error", 344 text: response.data.message, 345 type: "error", 346 }); 347 } 348 }) 349 .catch(function (error) { 350 console.error(error); 351 }); 352 } 353 }); 354 }, 355 getChecked: function () { 356 return this.sharesWithMe 357 .filter(function (e) { 358 return e.checked; 359 }) 360 .map(function (e) { 361 return e.sub; 362 }); 363 }, 364 hasChecked: function () { 365 return this.sharesWithMe.filter(function (e) { 366 return e.checked; 367 }).length; 368 }, 369 toggleCheck: function (idx) { 370 this.sharesWithMe[idx].checked = !this.sharesWithMe[idx].checked; 371 }, 372 toggleCheckAll: function () { 373 var vm = this; 374 vm.checkAll = !vm.checkAll; 375 this.sharesWithMe.forEach(function (obj, idx) { 376 if ($("#check_" + idx).length) { 377 $("#check_" + idx).prop("checked", vm.checkAll); 378 obj.checked = vm.checkAll; 379 } 380 }); 381 }, 382 importCustomSet: function () { 383 var vm = this; 384 axios 385 .get( 386 "https://study.lingolab.online/lingolabco.class.php?action=getSet&set=" + 387 this.importSetId 388 ) 389 .then(function (response) { 390 vm.importSetId = ""; 391 if (response.data.set) { 392 vm.customGridData = []; 393
394 response.data.set.terms.forEach(function (obj) { 395 vm.customGridData.push([ 396 obj.term, 397 obj.definition, 398 obj.image ? obj.image : "", 399 ]); 400 }); 401 402 vm.screen = "create_set"; 403 vm.setName = response.data.set.name; 404 vm.setLangs = response.data.set.languages; 405 } else { 406 Swal.fire({ 407 title: "Error", 408 text: "Invalid set!", 409 type: "error", 410 }); 411 } 412 }) 413 .catch(function (error) { 414 console.log(error); 415 }); 416 }, 417 removeProgressRecord: function (set, student) { 418 var vm = this; 419 Swal.fire({ 420 reverseButtons: true, 421 title: "Warning", 422 text: 423 "Are you sure you wish to remove progress on '" + 424 set.name + 425 "' for '" + 426 student.name + 427 "'?", 428 showCancelButton: true, 429 }).then(function (value) { 430 if (value.value) { 431 Swal.fire({ 432 onOpen: () => { 433 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 434 }, 435 }); 436 axios 437 .post("/lingolab_online.class.php", { 438 action: "removeProgressRecord", 439 data: { 440 set: set, 441 student: student, 442 }, 443 }) 444 .then(function (response) { 445 Swal.close(); 446 if (response.data.result == "success") { 447 vm.sharesWithMe = response.data.sharesWithMe; 448 } else { 449 Swal.fire({ 450 reverseButtons: true, 451 title: "Error", 452 text: response.data.message, 453 type: "error", 454 }); 455 } 456 }) 457 .catch(function (error) { 458 console.error(error); 459 }); 460 } 461 }); 462 }, 463 getSetsByStudent: function (student) { 464 return this.sharesWithMe.filter(function (e) { 465 return e.id == student.id; 466 })[0].progress; 467 }, 468 showStudentRecord: function (record) { 469 var vm = this; 470 var progress = this.getSetsByStudent(record); 471 var summary = this.totalProgressSummary(progress); 472 var html = 473 "<div><div style='font-size:20px;'>Current Total: " + 474 record.current_score + 475 " Running Total: " + 476 record.total_score + 477 "<br/>Last Active: " + 478 this.UTCToLocal(summary.last_active).substring(0, 10) + 479 "</div>"; 480 html += 481 "<div class='studentRecordDiv'><table class='table table-sm table-striped student-record-table'>"; 482 html += 483 "<thead class='thead-dark'><th>Set</th><th>Letters</th><th>Audio</th><th>Mastered</th><th>Errors</th><th>Last Studied</th></thead>"; 484 html += "<tbody>"; 485 var progressSummary; 486 progress.forEach(function (p) { 487 progressSummary = vm.progressSummary(p.progress_data); 488 html += 489 "<tr><td style='width:30%'>" + 490 p.set_name + 491 "</td><td style='width:10%'>" + 492 p.display.toUpperCase() + 493 "</td><td style='width:10%'>" + 494 p.audio.toUpperCase() + 495 "</td><td style='width:10%'>" + 496 progressSummary.mastered + 497 "</td><td style='width:10%'>" + 498 progressSummary.mistakes + 499 "</td><td style='width:20%'>" + 500 vm.UTCToLocal(p.modified).substring(0, 10) + 501 "</td></tr>"; 502 }); 503 html += "</tbody>"; 504 html += "</table></div></div>"; 505 506 Swal.fire({ 507 onOpen: function () { 508 $(".student-record-table").tablesorter({ 509 theme: "bootstrap", 510 sortList: [[0, 0]], 511 }); 512 $("#myContainer").addClass("blurred"); 513 }, 514 reverseButtons: true, 515 title: record.name + "<br/>" + record.class_name, 516 html: html,
517 showCancelButton: false, 518 }).then(function (value) { 519 $("#myContainer").removeClass("blurred"); 520 }); 521 }, 522 progressSummaryBySet: function (set, sub) { 523 var vm = this; 524 var thisSummary = null; 525 this.sharesWithMe.forEach(function (record) { 526 if (record.sub == sub) { 527 record.progress.forEach(function (p) { 528 if ( 529 p.set_id == set.id && 530 p.text == set.text && 531 p.audio == set.audio && 532 p.display == set.display 533 ) { 534 thisSummary = vm.progressSummary(p.progress_data); 535 } 536 }); 537 } 538 }); 539 if (thisSummary === null) { 540 thisSummary = { 541 mastered: "-", 542 attempted: "-", 543 mistakes: "-", 544 last_active: "-", 545 av_mistakes_per_term: "-", 546 }; 547 } 548 return thisSummary; 549 }, 550 getStudentsBySet: function (set) { 551 var vm = this; 552 var students = []; 553 var setProgress = null; 554 this.sharesWithMe.forEach(function (record) { 555 setProgress = record.progress.find(function (e) { 556 return ( 557 e.text == set.text && 558 e.audio == set.audio && 559 e.display == set.display && 560 e.set_id == set.id 561 ); 562 }); 563 564 students.push({ 565 modified: setProgress ? setProgress.modified : 0, 566 class_name: record.class_name, 567 name: record.name, 568 sub: record.sub, 569 text: set.text, 570 audio: set.audio, 571 display: set.display, 572 resets: setProgress ? setProgress.resets : 0, 573 }); 574 }); 575 return students; 576 }, 577 numResultsBySet: function (set_id) { 578 var vm = this; 579 var results = 0; 580 this.sharesWithMe.forEach(function (user) { 581 results += user.progress.filter(function (p) { 582 return p.set_id == set_id; 583 }).length; 584 }); 585 return results; 586 }, 587 resetTracker() { 588 this.selectedTrackerStudent = ""; 589 this.selectedTrackerClass = ""; 590 this.selectedTrackerSet = ""; 591 this.sharesWithMe = []; 592 this.checkAll = false; 593 $("#checkAll").prop("checked", false); 594 }, 595 loadTracker: function () { 596 var vm = this; 597 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 598 axios 599 .get( 600 "/lingolab_online.class.php?action=loadTracker&name=" + 601 this.selectedTrackerStudent + 602 "&class_name=" + 603 this.selectedTrackerClass + 604 "&set_name=" + 605 this.selectedTrackerSet 606 ) 607 .then(function (response) { 608 Swal.close(); 609 vm.sharesWithMe = response.data; 610 vm.$forceUpdate(); 611 Vue.nextTick(function () { 612 $(".progress-tracker-table").tablesorter({ 613 theme: "bootstrap", 614 sortList: [[2, 1]], 615 }); 616 $(".progress-tracker-students:not(.tablesorter)").tablesorter({ 617 theme: "bootstrap", 618 sortList: [[3, 1]], 619 }); 620 }); 621 }) 622 .catch(function (error) { 623 console.log(error); 624 }); 625 }, 626 getFilteredSharedSets: function () { 627 var vm = this; 628 var sharedSets = this.getSharedSets(); 629 return sharedSets.filter(function (e) { 630 return ( 631 ((e.display == "full" && vm.mode_shown) || 632 (e.display == "hidden" && vm.mode_hidden) || 633 (e.display == "stellar" && vm.mode_stellar)) && 634 ((e.audio == "question" && vm.audio_definition) || 635 (e.audio == "answer" && vm.audio_target) || 636 (e.audio == "off" && vm.audio_off)) 637 ); 638 }); 639 }, 640 getSharedSets: function () { 641 var sharedSets = []; 642 this.sharesWithMe.forEach(function (record) { 643 record.progress.forEach(function (p) { 644 if ( 645 !sharedSets 646 .map(function (e) { 647 return e.id + "_" + e.text + "_" + e.audio + "_" + e.display; 648 }) 649 .includes( 650 p.set_id + "_" + p.text + "_" + p.audio + "_" + p.display 651 ) 652 ) { 653 sharedSets.push({ 654 name: p.set_name, 655 id: p.set_id, 656 text: p.text, 657 audio: p.audio, 658 display: p.display, 659 }); 660 } 661 }); 662 }); 663 sharedSets.sort(function (a, b) { 664 if (a.name < b.name) { 665 return -1; 666 } 667 if (a.name > b.name) { 668 return 1; 669 } 670 return 0; 671 }); 672 return sharedSets; 673 }, 674 totalProgressSummary: function (progress) { 675 var vm = this; 676 var mastered = 0, 677 attempted = 0, 678 mistakes = 0, 679 totalTerms = 0; 680 var dates = []; 681 progress.forEach(function (data) { 682 dates.push(data.modified); 683 data.progress_data.forEach(function (item) { 684 totalTerms++; 685 mistakes += item.mistakes; 686 if (item.rank == 3) { 687 mastered++; 688 } 689 if (item.attempted) { 690 attempted++; 691 } 692 }); 693 }); 694 dates.sort(function (a, b) { 695 return new Date(b) - new Date(a); 696 }); 697 var last_active = "0"; 698 if (dates.length) { 699 last_active = dates[0]; 700 } 701 var av_mistakes_per_term = (mistakes / attempted).toFixed(1); 702 return { 703 mastered: mastered, 704 attempted: attempted, 705 mistakes: mistakes, 706 last_active: last_active, 707 av_mistakes_per_term: isNaN(av_mistakes_per_term) 708 ? 0 709 : av_mistakes_per_term, 710 }; 711 }, 712 progressSummary: function (data) { 713 var mastered = 0, 714 attempted = 0, 715 mistakes = 0; 716 data.forEach(function (item) { 717 mistakes += item.mistakes; 718 if (item.rank == 3) { 719 mastered++; 720 } 721 if (item.attempted) { 722 attempted++; 723 } 724 }); 725 var av_mistakes_per_term = (mistakes / attempted).toFixed(1); 726 return { 727 mastered: mastered, 728 attempted: attempted, 729 mistakes: mistakes, 730 av_mistakes_per_term: isNaN(av_mistakes_per_term) 731 ? 0 732 : av_mistakes_per_term, 733 }; 734 }, 735 changeImage: function (obj) { 736 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 737 axios 738 .post("https://study.lingolab.online/lingolabco.class.php", { 739 action: "imageSearch", 740 data: { 741 term: obj.term, 742 }, 743 }) 744 .then(function (response) { 745 var code = "<div class='scroll-list'>";
746 response.data.matches.hits.forEach(function (hit) { 747 code += 748 "<img data-term='" + 749 obj.id + 750 "' class='imgSearchResult' src='" + 751 hit.previewURL + 752 "'>"; 753 }); 754 code += "</div>"; 755 Swal.fire({ 756 reverseButtons: true, 757 title: "Choose image:", 758 html: code, 759 showCancelButton: true, 760 showConfirmButton: false, 761 }); 762 }) 763 .catch(function (error) { 764 console.error(error); 765 }); 766 }, 767 uniqueID: function () { 768 return Math.random().toString(36).substr(2, 9); 769 }, 770 deleteSet: function (id) { 771 var self = this; 772 self.deletingSet = true; 773 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 774 axios 775 .post("/lingolab_online.class.php", { 776 action: "deleteSet", 777 data: { 778 id: id, 779 }, 780 }) 781 .then(function (response) { 782 self.deletingSet = false; 783 if (response.data.result == "success") { 784 Swal.fire("Success", "Set deleted!", "success"); 785 self.userSets = response.data.userSets; 786 self.screen = "manage_sets"; 787 } else { 788 Swal.fire("Error", response.data.message, "error"); 789 } 790 }) 791 .catch(function (error) { 792 console.error(error); 793 }); 794 }, 795 reset: function () { 796 this.editId = ""; 797 this.savingSet = false; 798 this.deletingSet = false; 799 this.toImport = ""; 800 this.terms = []; 801 this.setName = ""; 802 this.setLangs = { 803 definition: "en", 804 term: "en", 805 }; 806 this.screen = "manage_sets"; 807 }, 808 saveSet: function () { 809 var self = this; 810 811 if (this.editId == "") { 812 this.importSet(); 813 } 814 815 if (!this.terms.length) { 816 Swal.fire( 817 "Error", 818 "Please input at least one term / definition pair", 819 "error" 820 ); 821 } else { 822 var maxWords = 16; 823 var maxWordsExceeded = false; 824 var words; 825 this.terms.forEach(function (obj) { 826 words = obj.term.split(" "); 827 if (words.length > maxWords) { 828 maxWordsExceeded = true; 829 } 830 }); 831 832 if (maxWordsExceeded) { 833 Swal.fire( 834 "Warning", 835 "Set contains terms that exceed the maximum of 16 words.", 836 "error" 837 ); 838 } else { 839 this.savingSet = true; 840 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 841 axios 842 .post("/lingolab_online.class.php", { 843 action: "saveSet", 844 data: { 845 editId: this.editId, 846 name: this.setName, 847 set: { 848 terms: this.terms, 849 languages: this.setLangs, 850 }, 851 }, 852 }) 853 .then(function (response) { 854 self.savingSet = false; 855 if (response.data.result == "success") { 856 Swal.fire( 857 "Success", 858 "Set " + (self.editId == "" ? "created" : "updated"), 859 "success" 860 ); 861 self.userSets = response.data.userSets; 862 self.screen = "manage_sets"; 863 self.setName = ""; 864 self.setLangs = { 865 definition: "en", 866 term: "en", 867 }; 868 self.terms = []; 869 //self.editSet(response.data.shortid); 870 } else { 871 Swal.fire("Error", "Error saving set!", "error"); 872 } 873 }) 874 .catch(function (error) { 875 console.error(error); 876 }); 877 } 878 } 879 }, 880 importSet: function () { 881 var self = this; 882 var gridData = self.termsTable.getData(); 883 gridData.forEach(function (elements) { 884 if ( 885 elements.slice(0, 2).every(function (e) { 886 return e && e.trim() !== ""; 887 }) 888 ) { 889 self.terms.push({ 890 id: self.uniqueID(), 891 term: elements[0].trim(), 892 definition: elements[1].trim(), 893 image: elements[2] ? elements[2].trim() : null, 894 }); 895 } 896 }); 897 }, 898 editStudent: function (record) { 899 var vm = this; 900 var html = ` 901 902 <div class="form-group"> 903 <label>Name:</label> 904 <input type="text" class="form-control" id="newName"> 905 </div> 906 907 <div class="form-group"> 908 <label>Class:</label> 909 <input type="text" class="form-control" id="newClass"> 910 </div> 911 912 `; 913 Swal.fire({ 914 onOpen: function () { 915 $("#newName").val(record.name); 916 $("#newClass").val(record.class_name); 917 }, 918 title: "Edit Student", 919 showCancelButton: true, 920 html: html, 921 reverseButtons: true, 922 }).then((result) => { 923 if (result.value) { 924 axios 925 .post("/lingolab_online.class.php", { 926 action: "editStudent", 927 data: { 928 name: $("#newName").val(), 929 class_name: $("#newClass").val(), 930 sub: record.sub, 931 }, 932 }) 933 .then(function (response) { 934 if (response.data.result == "success") { 935 vm.loadTracker(); 936 } else { 937 Swal.fire({ 938 title: "Error", 939 text: response.data.message, 940 type: "error", 941 }); 942 } 943 }) 944 .catch(function (error) { 945 console.error(error); 946 }); 947 } 948 }); 949 }, 950 editSet: function (setId) { 951 var thisSet = this.userSets.filter(function (e) { 952 return e.shortid == setId; 953 })[0]; 954 this.editId = setId; 955 this.terms = thisSet.terms; 956 this.setName = thisSet.name; 957 this.setLangs = thisSet.languages; 958 this.screen = "create_set"; 959 }, 960 get_set: function (id) { 961 var vm = this; 962 axios 963 .get( 964 "https://study.lingolab.online/lingolabco.class.php?action=getSet&set=" + 965 id 966 ) 967 .then(function (response) { 968 if (response.data.set) { 969 vm.selectSet(response.data.set); 970 } else { 971 Swal.fire({ 972 title: "Error", 973 text: "Invalid set!", 974 type: "error", 975 }); 976 } 977 }) 978 .catch(function (error) { 979 console.log(error); 980 }); 981 }, 982 mobile_user: function () { 983 if ( 984 /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( 985 navigator.userAgent 986 ) 987 ) { 988 return true; 989 } else { 990 return false;
991 } 992 }, 993 getQRCode: function (assignment_id) { 994 var url = "https://www.lingolab.online/submit.php?id=" + assignment_id; 995 axios 996 .post("/lingolab_online.class.php", { 997 action: "generateQRCode", 998 data: { 999 assignment_id: assignment_id, 1000 url: url, 1001 }, 1002 }) 1003 .then(function (response) { 1004 if (response.data.result == "success") { 1005 Swal.fire({ 1006 reverseButtons: true, 1007 html: 1008 "<h5 style='margin-top:40px;'>" + 1009 url + 1010 " <i style='cursor:pointer;' data-clipboard-text='https://lingolab.online/submit.php?id=" + 1011 assignment_id + 1012 "' class='link-btn fas fa-paste'></i></h5><img src='data:image/png;base64," + 1013 response.data.b64 + 1014 "'><h3>Students Joined: " + 1015 response.data.num_submissions + 1016 "</h3><h2><a href='javascript:void(0)' onClick='app.getQRCode(" + 1017 assignment_id + 1018 ")'>Reload</a></h2>", 1019 showCloseButton: true,
1020 showCancelButton: false, 1021 showConfirmButton: false, 1022 }); 1023 } 1024 }) 1025 .catch(function (error) { 1026 console.error(error); 1027 }); 1028 }, 1029 selectAll: function () { 1030 this.assignment.set.terms.forEach(function (item) { 1031 item.selected = true; 1032 }); 1033 this.$forceUpdate(); 1034 }, 1035 selectNone: function () { 1036 this.assignment.set.terms.forEach(function (item) { 1037 item.selected = false; 1038 }); 1039 this.$forceUpdate(); 1040 }, 1041 numSelected: function () { 1042 if (this.assignment.set.terms) { 1043 return this.assignment.set.terms.filter(function (e) { 1044 return e.selected; 1045 }).length; 1046 } else { 1047 return 0; 1048 } 1049 }, 1050 hasImages: function (set) { 1051 var result = false; 1052 if (set.terms) { 1053 set.terms.forEach(function (object) { 1054 if (object.image) { 1055 result = true; 1056 } 1057 }); 1058 } 1059 return result; 1060 }, 1061 selectItem: function (item) { 1062 item.selected = !item.selected; 1063 this.$forceUpdate(); 1064 }, 1065 deleteAssignment: function (assignment_id) { 1066 var vm = this; 1067 Swal.fire({ 1068 reverseButtons: true, 1069 title: "Warning", 1070 text: "Are you sure you wish to delete this assignment and ALL related submissions??", 1071 showCancelButton: true, 1072 }).then(function (value) { 1073 if (value.value) { 1074 Swal.fire({ 1075 onOpen: () => { 1076 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 1077 }, 1078 }); 1079 axios 1080 .post("/lingolab_online.class.php", { 1081 action: "deleteAssignment", 1082 data: { 1083 assignment_id: assignment_id, 1084 }, 1085 }) 1086 .then(function (response) { 1087 if (response.data.result == "success") { 1088 vm.assignments = response.data.assignments; 1089 } 1090 }) 1091 .catch(function (error) { 1092 console.error(error); 1093 }); 1094 } 1095 }); 1096 }, 1097 UTCToLocal: function (date) { 1098 var local = moment(moment.utc(date).toDate()) 1099 .local() 1100 .format("YYYY-MM-DD HH:mm:ss"); 1101 return local; 1102 }, 1103 timeElapsedHuman: function (then) { 1104 var now = moment().utc().format(); 1105 return moment.duration(moment.utc(then).diff(moment(now))).humanize(); 1106 }, 1107 createAssignment: function () { 1108 var vm = this; 1109 axios 1110 .post("/lingolab_online.class.php", { 1111 action: "createAssignment", 1112 data: { 1113 assignmentEditId: this.assignmentEditId, 1114 assignment: this.assignment, 1115 }, 1116 }) 1117 .then(function (response) { 1118 if (response.data.result == "success") { 1119 Swal.fire({ 1120 reverseButtons: true, 1121 title: "Success", 1122 html: 1123 "Assignment created at:<br/><a target='_blank' href='https://lingolab.online/submit.php?id=" + 1124 response.data.id + 1125 "'>https://lingolab.online/submit.php?id=" + 1126 response.data.id + 1127 "</a>", 1128 type: "success", 1129 }); 1130 vm.assignments = response.data.assignments; 1131 vm.screen = "manage"; 1132 } else { 1133 Swal.fire({ 1134 reverseButtons: true, 1135 title: "Error", 1136 text: response.data.message, 1137 type: "error", 1138 }); 1139 } 1140 }) 1141 .catch(function (error) { 1142 console.error(error); 1143 }); 1144 }, 1145 ucfirst: function (str) { 1146 str += ""; 1147 var f = str.charAt(0).toUpperCase(); 1148 return f + str.substr(1); 1149 }, 1150 selectSet: function (set) { 1151 this.assignment.set = set; 1152 this.assignment.set.terms.forEach(function (item) { 1153 item.mistakes = 0; 1154 item.selected = true; 1155 }); 1156 }, 1157 signIn: function (googleUser) { 1158 var vm = this; 1159 1160 axios 1161 .post("/lingolab_online.class.php", {
1162 action: "saveSignIn", 1163 data: { 1164 userToken: googleUser.credential, 1165 }, 1166 }) 1167 .then(function (response) { 1168 if (vm.user.role == "guest") { 1169 location.reload(); 1170 } 1171 }) 1172 .catch(function (error) { 1173 console.error(error); 1174 }); 1175 }, 1176 1177 signOut: function () { 1178 axios 1179 .post("/lingolab_online.class.php", { 1180 action: "signOut", 1181 data: {}, 1182 }) 1183 .then(function (response) { 1184 location.reload(); 1185 }) 1186 .catch(function (error) { 1187 console.error(error); 1188 }); 1189 }, 1190 }, 1191 created: function () { 1192 if (localStorage.getItem("infoWasShown")) { 1193 this.infoWasShown = true; 1194 } 1195 }, 1196 mounted: function () { 1197 var vm = this; 1198 1199 var clipboard = new ClipboardJS(".link-btn"); 1200 clipboard.on("success", function (e) { 1201 alertify.success("Copied!"); 1202 }); 1203 1204 $("body").on("click", ".imgSearchResult", function () { 1205 var imgUrl = $(this).attr("src"); 1206 var termId = $(this).data("term"); 1207 1208 Swal.fire({ title: 'Loading...', onBeforeOpen: () => Swal.showLoading(), allowOutsideClick: false }); 1209 1210 axios 1211 .post("https://study.lingolab.online/lingolabco.class.php", { 1212 action: "saveImage", 1213 data: { 1214 termId: termId, 1215 imgUrl: imgUrl, 1216 }, 1217 }) 1218 .then(function (response) { 1219 if (response.data.result == "success") { 1220 var term = app.terms.filter(function (term) { 1221 return term.id == termId; 1222 })[0]; 1223 term.image = 1224 "https://study.lingolab.online/set_images/" + termId + ".jpg"; 1225 Swal.close(); 1226 } else { 1227 Swal.fire("Error", response.data.message, "error"); 1228 } 1229 }) 1230 .catch(function (error) { 1231 console.error(error); 1232 }); 1233 }); 1234 1235 axios 1236 .get( 1237 "https://study.lingolab.online/lingolabco.class.php?action=getDefaultSets&list=lingolab" 1238 ) 1239 .then(function (response) { 1240 response.data.sort(function (a, b) { 1241 if (a.name < b.name) { 1242 return -1; 1243 } 1244 if (a.name > b.name) { 1245 return 1; 1246 } 1247 return 0; 1248 }); 1249 1250 vm.defaultSets = response.data; 1251 }) 1252 .catch(function (error) { 1253 console.log(error); 1254 }); 1255 1256 axios 1257 .get("/lingolab_online.class.php?action=getUserSets") 1258 .then(function (response) { 1259 if (response.data.result == "success") { 1260 vm.userSets = response.data.sets; 1261 Vue.nextTick(function () { 1262 vm.sort_tables(); 1263 }); 1264 } 1265 }) 1266 .catch(function (error) { 1267 console.log(error); 1268 }); 1269 1270 $(window).resize(function () { 1271 if (vm.screen == "create_set") { 1272 Vue.nextTick(function () { 1273 vm.termsTable.render(); 1274 }); 1275 } 1276 }); 1277 1278 if (this.get_url_param("screen")) { 1279 this.screen = this.get_url_param("screen"); 1280 } else { 1281 this.screen = "manage"; 1282 } 1283 }, 1284});
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.