subgroup.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * ЭЛЕКТРОННЫЙ ЖУРНАЛ «ШКАЛА»: РАЗБИЕНИЕ КЛАССА НА ПОДГРУППЫ
  3. * Copyright © 2019, А.М.Гольдин. Modified BSD License
  4. */
  5. "use strict";
  6. // Переключение содержимого ячейки таблицы с галочки на пустую и обратно
  7. const turnMark = elem => {
  8. elem.innerHTML = elem.innerHTML ? '' : '■';
  9. }
  10. // Добавление/удаление подгруппы из списка
  11. // (имя подгруппы типа "мальч" без префикса класса!)
  12. // f - это "add" или "del"
  13. const subGrEdit = async (sbGrName, f) => {
  14. let className = dqs("#sgrClassSel").value;
  15. if (f == "del")
  16. if (!confirm(`Удалить подгруппу "${sbGrName}"?`)) return;
  17. if (f == "add") {
  18. sbGrName = dqs("#subGrNew").value.trim();
  19. if (!sbGrName) {info(1, "Введите имя подгруппы!"); return;}
  20. if (!/^[а-яё0-9]{1,10}$/.test(sbGrName)) {
  21. info(1, "Имя подгруппы может<br>содержать от 1 до 10<br>строчных "
  22. + "русских букв<br>и (возможно) цифр.");
  23. return;
  24. }
  25. }
  26. dqs("#subGrNew").value = '';
  27. let fullName = `${className}-${sbGrName}`;
  28. let apiResp = await apireq("subgrEdit", [className, fullName, f]);
  29. if (apiResp == "none") {info(1, "Ошибка на сервере"); return;}
  30. else subGroupsLoad(className);
  31. }
  32. // Получение списка существующих подгрупп данного класса
  33. const subGroupsLoad = async (className) => {
  34. let apiResp = await apireq("classesGroups");
  35. if (apiResp != "none") {
  36. let groupsList = JSON.parse(apiResp);
  37. groupsList = groupsList.filter(x => {
  38. if (x.includes('-')) return (x.split('-')[0] == className);
  39. else return false;
  40. });
  41. // Если подгруппы есть, публикуем их с иконками удаления
  42. if (groupsList.length) {
  43. groupsList = groupsList
  44. . map(x => x.replace(className + '-', '')).sort();
  45. let cont = '';
  46. for (let sGroup of groupsList)
  47. cont += `<div><div onclick="subGrEdit('${sGroup}', 'del')">`
  48. + `&#10060;</div>${sGroup}</div>`;
  49. dqs("#subGrList").innerHTML = cont;
  50. // Формируем селект выбора подгруппы для редактирования ее состава
  51. let inner = '';
  52. for (let gr of groupsList) inner += `<option>${gr}</option>`;
  53. dqs("#sgrGroupSel").innerHTML = inner;
  54. subGroupPups(groupsList[0]);
  55. }
  56. else dqs("#subGrList").innerHTML = "Подгрупп не найдено";
  57. }
  58. else dqs("#subGrList").innerHTML = "Подгрупп не найдено";
  59. }
  60. // Публикация формы редактирования списочного состава одной подгруппы
  61. // (имя подгруппы типа "мальч" без префикса класса!)
  62. const subGroupPups = async (sbGrName) => {
  63. let className = dqs("#sgrClassSel").value,
  64. fullName = `${className}-${sbGrName}`,
  65. cont = '';
  66. let apiResp = await apireq("gradesGet", [className, '', "a"]);
  67. if (apiResp != "none") {
  68. let rObj = JSON.parse(apiResp);
  69. // Получаем логины членов подгруппы
  70. let grResp = await apireq("gradesGet", [fullName, '', "a"]);
  71. if (grResp == "none") {info(1, "Ошибка на сервере"); return;}
  72. let grObj = JSON.parse(grResp);
  73. let grArr = grObj.puList ? grObj.puList : [];
  74. cont += "<table>";
  75. for (let i = 0; i < rObj.puList.length; i++) {
  76. let checked = grArr.includes(rObj.puList[i]) ? '■' : '';
  77. cont += `<tr data-uid="${rObj.puList[i]}">
  78. <td>${rObj.pnList[i]}</td>
  79. <td onClick="turnMark(this)">${checked}</td>
  80. </tr>`;
  81. }
  82. cont += "</table>";
  83. cont += `<button type="button" onClick="sgrPupsEd('${fullName}')"
  84. >Сохранить изменения</button>`;
  85. }
  86. else cont = "Список учащихся не получен с сервера"
  87. dqs("#subGrEdit").innerHTML = cont;
  88. }
  89. // Редактирование списочного состава одной подгруппы (запрос к API)
  90. const sgrPupsEd = async (subrgName) => {
  91. // Формируем массив логинов отмеченных учащихся
  92. // (самый первый элемент - название подгруппы!)
  93. let grLoginsArr = [subrgName];
  94. let trElems = document.querySelectorAll("#subgroup table tr");
  95. for (let tr of trElems)
  96. if (tr.innerHTML.includes('■')) grLoginsArr.push(tr.dataset.uid);
  97. // Отправляем запрос к API
  98. info(0, "Ждите...<br><img src='static/preloader.gif'>");
  99. let grResp = await apireq("subgrPups", grLoginsArr);
  100. if (grResp == "none") {info(1, "Ошибка на сервере"); return;}
  101. else info(0, "Состав подгруппы успешно обновлен.");
  102. }
  103. // Формируем контент странички
  104. createSection("subgroup", `
  105. <select id="sgrClassSel" onChange="subGroupsLoad(this.value);"></select>
  106. <h3>Подгруппы вашего класса</h3>
  107. <div id="subGrList"></div>
  108. <input id="subGrNew" maxlength="10" placeholder="Новая подгруппа"
  109. onKeyDown="if (event.keyCode == 13) subGrEdit('', 'add')">
  110. <button type="button" onClick="subGrEdit('', 'add')">Добавить</button>
  111. <h3>Редактирование состава подгруппы</h3>
  112. <select id="sgrGroupSel" onChange="subGroupPups(this.value);"></select>
  113. <div id="subGrEdit"></div>
  114. `);
  115. // Динамически подгружаем контент страницы (имя метода = имени пункта меню!)
  116. getContent.subgroup = async () => {
  117. // Формирование списка классов в селекте (uTutorCls определен в login.js)
  118. let sgrSelClInner = '';
  119. for (let cls of uTutorCls) sgrSelClInner += `<option>${cls}</option>`;
  120. dqs("#sgrClassSel").innerHTML = sgrSelClInner;
  121. // Загружаем список подгрупп {первого класса в списке классов}
  122. subGroupsLoad(dqs("#sgrClassSel").value);
  123. }