pref-matrix

Web interface to coordinate preferences
git clone https://git.instinctive.eu/pref-matrix.git
Log | Files | Refs | README | LICENSE

edit.html (9134B)


      1 <!DOCTYPE html>
      2 <html lang="fr">
      3   <head>
      4     <meta charset="utf-8" />
      5     <meta name="viewport" content="width=device-width">
      6     <title>Planification JDR</title>
      7     <link rel="stylesheet" type="text/css" href="style.css" />
      8     <script>
      9 var val_class=["val0","val1","val2","val3","val4","val5"];
     10 var val_text=["?","−−","−","0","+","++"];
     11 var all_data=null;
     12 var radio_map=new Map();
     13 var spinner_map=new Map();
     14 var subject=null;
     15 var sent=null;
     16 var outbox=new Map();
     17 var sender=null;
     18 var base_timeout=2000;
     19 var retry_timeout=base_timeout;
     20 
     21 window.onerror = function(msg, url, line) {
     22   var item = document.createElement("li");
     23   item.appendChild(document.createTextNode(url + "@" + line + ": " + msg));
     24   document.getElementById("error-log").appendChild(item);
     25   document.getElementById("error-div").style = "display:block";
     26   item.scrollIntoView();
     27 }
     28 
     29 function pathname_to_topic(str) {
     30   var components = str.split("/");
     31   var fileName = components[components.length - 1];
     32   var lastDotIndex = fileName.lastIndexOf("-");
     33   return lastDotIndex !== -1 ? fileName.substring(0, lastDotIndex) : "";
     34 }
     35 
     36 var topic=pathname_to_topic(window.location.pathname);
     37 
     38 async function send(){
     39   var req_body = (topic ? "topic=" + encodeURIComponent(topic) + "&" : "") + "sub=" + encodeURIComponent(subject);
     40   for (const [key, value] of outbox) {
     41     req_body += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(value);
     42   }
     43   sent = outbox;
     44   outbox = new Map();
     45   const response = await fetch("do/set-pref", {
     46     method: "POST",
     47     cache: "no-store",
     48     headers: { "Content-Type": "application/x-www-form-urlencoded" },
     49     body: req_body,
     50   });
     51   var to = base_timeout;
     52   if (response.ok) {
     53     for (const [key, value] of sent) {
     54       if (!outbox.has(key)) {
     55         spinner_map.get(key).style = "display:none";
     56       }
     57     }
     58     retry_timeout = base_timeout;
     59   } else {
     60     for (const [key, value] of sent) {
     61       if (!outbox.has(key)) {
     62         outbox.set(key, value);
     63       }
     64     }
     65     to = retry_timeout;
     66     retry_timeout *= 2;
     67   }
     68   sent = null;
     69   if (outbox.size) {
     70     sender = setTimeout(send, to);
     71   }
     72 }
     73 
     74 function radio_click(name, value){
     75   spinner_map.get(name).style = "display:inline";
     76   outbox.set(name, value);
     77   if (!sent) {
     78     if (sender) {
     79       clearTimeout(sender);
     80     }
     81     sender = setTimeout(send, 2000);
     82   }
     83 }
     84 
     85 function new_table_line(name) {
     86   var line = document.createElement("tr");
     87 
     88   var cell = document.createElement("td");
     89   cell.className = "date";
     90   cell.appendChild(document.createTextNode(name));
     91   line.appendChild(cell);
     92 
     93   var radios = new Array;
     94 
     95   for (const i in val_text) {
     96     cell = document.createElement("td");
     97     var elt1 = document.createElement("label");
     98     var elt2 = document.createElement("input");
     99     elt2.type = "radio";
    100     elt2.name = name;
    101     elt2.value = i;
    102     elt2.onchange = function() { radio_click(name, i) };
    103     radios[i] = elt2;
    104     elt1.appendChild(elt2);
    105     elt1.appendChild(document.createTextNode(val_text[i]));
    106     elt1.className = val_class[i];
    107     cell.appendChild(elt1);
    108     if (i > 0) {
    109       line.appendChild(cell);
    110     } else {
    111       line.insertBefore(cell, line.childNodes[0]);
    112     }
    113   }
    114   radio_map.set(name, radios);
    115 
    116   cell = document.createElement("td");
    117   elt1 = document.createElement("img");
    118   elt1.className = "spinner";
    119   elt1.src = "spinner.svg";
    120   elt1.style = "display:none";
    121   spinner_map.set(name, elt1);
    122   cell.appendChild(elt1);
    123   line.appendChild(cell);
    124 
    125   return line;
    126 }
    127 
    128 function activate_subject(){
    129   document.getElementById("cur-subject").textContent = subject;
    130 
    131   if (!subject) {
    132     document.getElementById("change-form").style = "display:block";
    133     document.getElementById("cur-subject-p").style = "display:none";
    134     document.getElementById("pref-form").style = "display:none";
    135     document.getElementById("new-subject").style = "display:none";
    136     return false;
    137   } else if (subject in all_data[1]) {
    138     for (const [name, radios] of radio_map) {
    139       for (const i in val_text) {
    140         radios[i].checked = (i == (all_data[1][subject][name] || 0));
    141       }
    142     }
    143 
    144     document.getElementById("change-form").style = "display:none";
    145     document.getElementById("cur-subject-p").style = "display:block";
    146     document.getElementById("pref-form").style = "display:block";
    147     document.getElementById("new-subject").style = "display:none";
    148     return false;
    149   } else {
    150     document.getElementById("change-form").style = "display:none";
    151     document.getElementById("cur-subject-p").style = "display:block";
    152     document.getElementById("pref-form").style = "display:none";
    153     document.getElementById("new-subject").style = "display:block";
    154     return true;
    155   }
    156 }
    157 
    158 async function reload_data(){
    159   document.getElementById("back-link").href = (topic ? topic + "-" : "") + "view.html";
    160   document.getElementById("reload-spinner").style = "display:inline";
    161   const response = await fetch((topic || "all") + ".json", { cache: "no-cache" });
    162   all_data = await response.json();
    163 
    164   var holder = document.getElementById("pref-table-body");
    165   while (holder.childNodes.length > 0) {
    166     holder.removeChild(holder.childNodes[0]);
    167   }
    168 
    169   var line = null;
    170   var cell = null;
    171   var elt1 = null;
    172   var elt2 = null;
    173 
    174   radio_map.clear();
    175   spinner_map.clear();
    176 
    177   for (const name of all_data[0]) {
    178     holder.appendChild(new_table_line(name));
    179   }
    180 
    181   subject = localStorage.getItem("subject" + (topic ? "-" + topic : ""));
    182   activate_subject();
    183 
    184   document.getElementById("reload-spinner").style = "display:none";
    185 }
    186 
    187 async function create_subject(){
    188   document.getElementById("create-spinner").style = "display:inline";
    189   const response = await fetch("do/new-subject", {
    190     method: "POST",
    191     cache: "no-store",
    192     headers: { "Content-Type": "application/x-www-form-urlencoded" },
    193     body: (topic ? "topic=" + encodeURIComponent(topic) + "&" : "") + "name=" + encodeURIComponent(subject),
    194   });
    195   document.getElementById("create-spinner").style = "display:none";
    196 
    197   if (response.ok) {
    198     document.getElementById("new-subject").style = "display:none";
    199     reload_data();
    200   }
    201 }
    202 
    203 function set_subject(){
    204   subject = document.getElementById("set-subject").value;
    205   localStorage.setItem("subject" + (topic ? "-" + topic : ""), subject);
    206   activate_subject();
    207   return false;
    208 }
    209 
    210 function reset_subject(){
    211   document.getElementById("change-form").style = "display:block";
    212   document.getElementById("cur-subject-p").style = "display:none";
    213 }
    214     </script>
    215   </head>
    216   <body onload="reload_data()">
    217     <h1>Planification JDR</h1>
    218     <p>
    219       <a href="view.html" id="back-link">Retour à la vue d'ensemble</a>
    220       <input name="test" value="Recharger" type="button" onclick="reload_data()">
    221       <img id="reload-spinner" class="spinner" src="spinner.svg" style="display: none">
    222     </p>
    223     <table style="margin: 1em">
    224       <tr><td colspan="2" style="text-align: left"><strong>Symboles des préférences :</strong></td></tr>
    225       <tr>
    226         <td class="val5">++</td>
    227         <td style="text-align: left">j'ai très envie de jouer ce soir-là, je vais m'ennuyer autrement</td>
    228       </tr>
    229       <tr>
    230         <td class="val4">+</td>
    231         <td style="text-align: left">j'aimerais bien jouer ce soir-là</td>
    232       </tr>
    233       <tr>
    234         <td class="val3">0</td>
    235         <td style="text-align: left">je veux bien jouer mais ça ne me dérange pas de ne pas jouer</td>
    236       </tr>
    237       <tr>
    238         <td class="val2">−</td>
    239         <td style="text-align: left">je peux jouer ce soir-là mais ça ne m'arrange pas vraiment</td>
    240       </tr>
    241       <tr>
    242         <td class="val1">−−</td>
    243         <td style="text-align: left">je ne suis pas du tout disponible ce soir-là</td>
    244       </tr>
    245       <tr>
    246         <td class="val0">?</td>
    247         <td style="text-align: left">je ne veux pas me prononcer</td>
    248       </tr>
    249     </table>
    250     <form id="change-form" onsubmit="return set_subject()">
    251       <p>
    252         <label>
    253           Pseudo : <input name="subject" id="set-subject" value="" type="text">
    254         </label>
    255         <input name="submit" value="Valider" type="submit">
    256       </p>
    257     </form>
    258     <p id="cur-subject-p" style="display:none">
    259       Préférences pour <strong id=cur-subject></strong>
    260       <input name="change-subject" value="Changer" type="button" onclick="reset_subject()">
    261     </p>
    262     <form id="pref-form" style="display:block">
    263       <table>
    264         <thead>
    265           <tr id="table-header">
    266             <th></th>
    267             <th>Date</th>
    268             <th colspan="5">Préférence</th>
    269             <th></th>
    270           </tr>
    271         </thead>
    272         <tbody id="pref-table-body">
    273           <tr>
    274             <td colspan="8">
    275               <img src="spinner.svg" with="5em" height"5em">
    276             </td>
    277           </tr>
    278         </tbody>
    279       </table>
    280     </form>
    281     <p id="new-subject" style="display:none">
    282       <input name="submit" type="button" value="Créer" onclick="create_subject()">
    283       <img id="create-spinner" class="spinner" src="spinner.svg" style="display: none">
    284     </p>
    285     <div id="error-div" style="display:none">
    286       <p>Error log:</p>
    287       <ul id="error-log"><ul>
    288     </div>
    289   </body>
    290 </html>