• דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private
    • הרשמה
    • התחברות

    פאנל ניהול מותאם אישית

    מתוזמן נעוץ נעול הועבר עזרה הדדית למשתמשים מתקדמים
    35 פוסטים 3 כותבים 49 צפיות 2 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • א מנותק
      אA @BEN ZION
      נערך לאחרונה על ידי

      @BEN-ZION
      התכוונתי מה נצרך להכניס בכזה פאנל.
      הצורך בכזה דבר מאוד ברור...

      B תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • B מנותק
        BEN ZION @אA
        נערך לאחרונה על ידי

        @אA את כל הניהול הבסיסי של שלוחה: העלאת קבצים, הורדה, מחיקה, ניהול קבצי EXT, INI, אפשרות לניהול רשימ"ת ספציפית,
        זה בגדול אולי יש עוד פרטים שאני לא זוכר

        א תגובה 1 תגובה אחרונה תגובה ציטוט 0
        • א מנותק
          אA @BEN ZION
          נערך לאחרונה על ידי

          @BEN-ZION

          1. העלאה
          2. הורדה
          3. מחיקה
          4. ניהול רשי"ת
          5. ניהול קבצי ini

          ניהול קבצי ext נראה לי קצת פחות, הרי מזה בדיוק אתה מםחד שיטפלו בזה, לא?

          B ל 2 תגובות תגובה אחרונה תגובה ציטוט 0
          • B מנותק
            BEN ZION @אA
            נערך לאחרונה על ידי

            @אA נכון אבל בשלוחה שלו אם ירצה להוסיף שלוחה פנימית יהיה חייב לערוך

            לא אכפת לי שבשלוחה שלו יהיה נזק העיקר שהקו מתפקד

            תגובה 1 תגובה אחרונה תגובה ציטוט 0
            • ל מנותק
              לימוד בתורת מרן @אA
              נערך לאחרונה על ידי לימוד בתורת מרן

              @אA
              אם כבר מפתחים
              להוסיף פיצ'רים לרשימת צינתוקים
              וברישמת תפוצה נגיד לוג מי נוסף ומתי ואיך

              ל תגובה 1 תגובה אחרונה תגובה ציטוט 0
              • ל מנותק
                לימוד בתורת מרן @לימוד בתורת מרן
                נערך לאחרונה על ידי

                פעם פיתכתי משהו בערך
                @אa
                @ben-zion
                יש את זה yemot_basic_manager.html

                B תגובה 1 תגובה אחרונה תגובה ציטוט 0
                • B מנותק
                  BEN ZION @לימוד בתורת מרן
                  נערך לאחרונה על ידי

                  @לימוד-בתורת-מרן תעלה את הקוד אי אפשר להעלות ככה או שתדחוס את זה

                  ל 2 תגובות תגובה אחרונה תגובה ציטוט 0
                  • ל מנותק
                    לימוד בתורת מרן @BEN ZION
                    נערך לאחרונה על ידי

                    @BEN-ZION
                    מעלה את הקוד

                    תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • ל מנותק
                      לימוד בתורת מרן @BEN ZION
                      נערך לאחרונה על ידי

                      פוסט זה נמחק!
                      ל תגובה 1 תגובה אחרונה תגובה ציטוט 0
                      • ל מנותק
                        לימוד בתורת מרן @לימוד בתורת מרן
                        נערך לאחרונה על ידי לימוד בתורת מרן

                        @ben-zion
                        קוד חדש
                        כותבים פקודה בapi
                        ועוד דברים זה ישן

                        <!doctype html>
                        <html lang="he" dir="rtl">
                        <head>
                          <meta charset="utf-8" />
                          <meta name="viewport" content="width=device-width,initial-scale=1" />
                          <title>ניהול בסיסי לשלוחה - ימות המשיח</title>
                          <style>
                            body{
                              font-family:Arial,sans-serif;
                              background:#f4f6f9;
                              margin:0;
                              padding:20px;
                              color:#222;
                            }
                            .wrap{
                              max-width:1000px;
                              margin:auto;
                            }
                            h1{
                              margin:0 0 20px;
                              background:#243447;
                              color:#fff;
                              padding:14px;
                              border-radius:12px;
                              font-size:24px;
                            }
                            .grid{
                              display:grid;
                              grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
                              gap:16px;
                            }
                            .card{
                              background:#fff;
                              border-radius:14px;
                              padding:16px;
                              box-shadow:0 2px 10px rgba(0,0,0,.08);
                            }
                            .card h2{
                              margin-top:0;
                              font-size:20px;
                            }
                            label{
                              display:block;
                              margin:10px 0 5px;
                              font-weight:bold;
                            }
                            input, textarea, select, button{
                              width:100%;
                              box-sizing:border-box;
                              padding:10px;
                              border:1px solid #cfd7df;
                              border-radius:10px;
                              font-size:15px;
                            }
                            textarea{
                              min-height:130px;
                              resize:vertical;
                              font-family:monospace;
                            }
                            button{
                              background:#0b57d0;
                              color:#fff;
                              border:none;
                              cursor:pointer;
                              font-weight:bold;
                              margin-top:10px;
                            }
                            button:hover{
                              opacity:.92;
                            }
                            .btn-danger{ background:#c62828; }
                            .btn-green{ background:#2e7d32; }
                            .btn-gray{ background:#546e7a; }
                            .row{
                              display:grid;
                              grid-template-columns:1fr 1fr;
                              gap:10px;
                            }
                            .small{
                              font-size:13px;
                              color:#666;
                              margin-top:6px;
                            }
                            #filesTable{
                              width:100%;
                              border-collapse:collapse;
                              margin-top:10px;
                              font-size:14px;
                            }
                            #filesTable th,#filesTable td{
                              border:1px solid #ddd;
                              padding:8px;
                              text-align:right;
                            }
                            #filesTable th{
                              background:#eef3f8;
                            }
                            pre{
                              background:#111;
                              color:#7CFC00;
                              padding:14px;
                              border-radius:12px;
                              min-height:180px;
                              overflow:auto;
                              white-space:pre-wrap;
                              word-break:break-word;
                            }
                            .muted{
                              color:#888;
                              font-size:13px;
                            }
                          </style>
                        </head>
                        <body>
                        <div class="wrap">
                          <h1>ניהול בסיסי לשלוחה - ימות המשיח</h1>
                        
                          <div class="card" style="margin-bottom:16px;">
                            <h2>הגדרות כלליות</h2>
                            <label>טוקן</label>
                            <input id="token" placeholder="077XXXXXXX:XXXXXX" />
                        
                            <label>נתיב שלוחה</label>
                            <input id="path" placeholder="לדוגמה: 1/2/3" />
                        
                            <div class="small">הנתיב יישלח ל־API כ־ivr2:1/2/3</div>
                          </div>
                        
                          <div class="grid">
                        
                            <div class="card">
                              <h2>העלאת קובץ</h2>
                              <label>בחר קובץ</label>
                              <input type="file" id="uploadFileInput" />
                        
                              <label>שם יעד לקובץ (לא חובה)</label>
                              <input id="targetFileName" placeholder="לדוגמה: 000.wav או ext.ini" />
                        
                              <label>
                                <input type="checkbox" id="convertAudio" style="width:auto;transform:scale(1.2);margin-left:8px;">
                                המר אודיו ל־wav
                              </label>
                        
                              <button onclick="uploadFile()">העלה קובץ</button>
                            </div>
                        
                            <div class="card">
                              <h2>הורדת קובץ</h2>
                              <label>שם קובץ להורדה</label>
                              <input id="downloadFileName" placeholder="לדוגמה: 000.wav או ext.ini" />
                              <button class="btn-green" onclick="downloadFile()">הורד קובץ</button>
                            </div>
                        
                            <div class="card">
                              <h2>מחיקה</h2>
                              <label>שם קובץ / שלוחה למחיקה</label>
                              <input id="deleteName" placeholder="לדוגמה: 000.wav או 8" />
                              <button class="btn-danger" onclick="deleteItem()">מחק</button>
                            </div>
                        
                            <div class="card">
                              <h2>רשימת קבצים בשלוחה</h2>
                              <button class="btn-gray" onclick="getDir()">רענן רשימת קבצים</button>
                              <div id="filesArea" class="muted" style="margin-top:10px;">עדיין לא נטענה רשימה</div>
                            </div>
                        
                            <div class="card">
                              <h2>ניהול ext.ini</h2>
                              <div class="row">
                                <div>
                                  <button class="btn-gray" onclick="loadTextFile('ext.ini','extContent')">טען ext.ini</button>
                                </div>
                                <div>
                                  <button onclick="saveTextFile('ext.ini','extContent')">שמור ext.ini</button>
                                </div>
                              </div>
                              <label>תוכן ext.ini</label>
                              <textarea id="extContent" placeholder="type=menu&#10;title=בדיקה"></textarea>
                            </div>
                        
                            <div class="card">
                              <h2>ניהול קובץ INI</h2>
                              <label>שם קובץ ini</label>
                              <input id="iniFileName" placeholder="לדוגמה: M1000.ini" />
                              <div class="row">
                                <div>
                                  <button class="btn-gray" onclick="loadNamedIni()">טען קובץ ini</button>
                                </div>
                                <div>
                                  <button onclick="saveNamedIni()">שמור קובץ ini</button>
                                </div>
                              </div>
                              <label>תוכן קובץ ini</label>
                              <textarea id="iniContent"></textarea>
                            </div>
                        
                            <div class="card">
                              <h2>ניהול קובץ EXT נוסף</h2>
                              <label>שם קובץ ext</label>
                              <input id="extFileName" placeholder="לדוגמה: ext.ini או ext2.ini" />
                              <div class="row">
                                <div>
                                  <button class="btn-gray" onclick="loadNamedExt()">טען קובץ ext</button>
                                </div>
                                <div>
                                  <button onclick="saveNamedExt()">שמור קובץ ext</button>
                                </div>
                              </div>
                              <label>תוכן קובץ ext</label>
                              <textarea id="extCustomContent"></textarea>
                            </div>
                        
                            <div class="card">
                              <h2>ניהול רשימ&quot;ת / רשימת צינתוקים</h2>
                              <label>שם רשימה</label>
                              <input id="listName" placeholder="לדוגמה: 120" />
                        
                              <div class="row">
                                <div><button class="btn-gray" onclick="getLists()">הצג כל הרשימות</button></div>
                                <div><button class="btn-gray" onclick="getListEntries()">הצג מנויים</button></div>
                              </div>
                        
                              <div class="row">
                                <div><button class="btn-gray" onclick="getListLog()">הצג לוג</button></div>
                                <div><button class="btn-danger" onclick="resetList()">אפס רשימה</button></div>
                              </div>
                        
                              <div class="small">
                                לפי התיעוד שמצאתי: יש צפייה ברשימות, מנויים, לוג ואיפוס. לא מצאתי כאן פעולה ברורה להוספה/מחיקה ידנית של מספר דרך ה־API הרגיל.
                              </div>
                            </div>
                        
                          </div>
                        
                          <div class="card" style="margin-top:16px;">
                            <h2>לוג / פלט</h2>
                            <pre id="log"></pre>
                          </div>
                        </div>
                        
                        <script>
                          const API = "https://www.call2all.co.il/ym/api/";
                        
                          function log(msg, append = true) {
                            const el = document.getElementById("log");
                            const text = typeof msg === "string" ? msg : JSON.stringify(msg, null, 2);
                            el.textContent = append ? (el.textContent + (el.textContent ? "\n\n" : "") + text) : text;
                          }
                        
                          function clearLog() {
                            document.getElementById("log").textContent = "";
                          }
                        
                          function getToken() {
                            return document.getElementById("token").value.trim();
                          }
                        
                          function getPathRaw() {
                            return document.getElementById("path").value.trim().replace(/^\/+|\/+$/g, "");
                          }
                        
                          function getIvrPath() {
                            const p = getPathRaw();
                            return p ? `ivr2:${p}` : "ivr2:";
                          }
                        
                          function buildFullPath(fileName) {
                            const p = getPathRaw();
                            const cleanName = String(fileName || "").trim().replace(/^\/+/, "");
                            return p ? `ivr2:${p}/${cleanName}` : `ivr2:${cleanName}`;
                          }
                        
                          function ensureTokenAndPath() {
                            const token = getToken();
                            const path = getPathRaw();
                            if (!token) {
                              alert("נא להזין טוקן");
                              return null;
                            }
                            if (!path) {
                              alert("נא להזין נתיב שלוחה");
                              return null;
                            }
                            return { token, path };
                          }
                        
                          async function safeJson(res) {
                            const txt = await res.text();
                            try {
                              return JSON.parse(txt);
                            } catch {
                              return { raw: txt, httpStatus: res.status, ok: res.ok };
                            }
                          }
                        
                          async function uploadFile() {
                            clearLog();
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const fileInput = document.getElementById("uploadFileInput");
                            const file = fileInput.files[0];
                            if (!file) {
                              alert("נא לבחור קובץ");
                              return;
                            }
                        
                            const targetFileName = document.getElementById("targetFileName").value.trim() || file.name;
                            const convertAudio = document.getElementById("convertAudio").checked ? "1" : "0";
                        
                            const form = new FormData();
                            form.append("token", base.token);
                            form.append("path", buildFullPath(targetFileName));
                            form.append("convertAudio", convertAudio);
                            form.append("qqfile", file, file.name);
                        
                            try {
                              const res = await fetch(API + "UploadFile", {
                                method: "POST",
                                body: form
                              });
                              const data = await safeJson(res);
                              log(data, false);
                              await getDir();
                            } catch (e) {
                              log("שגיאה בהעלאה: " + e.message, false);
                            }
                          }
                        
                          function downloadFile() {
                            clearLog();
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const name = document.getElementById("downloadFileName").value.trim();
                            if (!name) {
                              alert("נא להזין שם קובץ");
                              return;
                            }
                        
                            const url = API + "DownloadFile?token=" + encodeURIComponent(base.token) +
                              "&path=" + encodeURIComponent(buildFullPath(name));
                        
                            log("פותח הורדה:\n" + url, false);
                            window.open(url, "_blank");
                          }
                        
                          async function deleteItem() {
                            clearLog();
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const name = document.getElementById("deleteName").value.trim();
                            if (!name) {
                              alert("נא להזין שם קובץ או שלוחה למחיקה");
                              return;
                            }
                        
                            if (!confirm("למחוק את: " + name + " ?")) return;
                        
                            const url = API + "FileAction?token=" + encodeURIComponent(base.token) +
                              "&action=delete" +
                              "&what=" + encodeURIComponent(buildFullPath(name));
                        
                            try {
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                              await getDir();
                            } catch (e) {
                              log("שגיאה במחיקה: " + e.message, false);
                            }
                          }
                        
                          async function getDir() {
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const url = API + "GetIVR2Dir?token=" + encodeURIComponent(base.token) +
                              "&path=" + encodeURIComponent(base.path);
                        
                            try {
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                              renderFiles(data);
                            } catch (e) {
                              log("שגיאה בקבלת רשימת קבצים: " + e.message, false);
                            }
                          }
                        
                          function renderFiles(data) {
                            const area = document.getElementById("filesArea");
                            const files = data && data.files ? data.files : [];
                        
                            if (!files.length) {
                              area.innerHTML = "לא נמצאו קבצים או שלא התקבלה רשימה.";
                              return;
                            }
                        
                            let html = `
                              <table id="filesTable">
                                <thead>
                                  <tr>
                                    <th>שם</th>
                                    <th>סוג</th>
                                    <th>גודל</th>
                                  </tr>
                                </thead>
                                <tbody>
                            `;
                        
                            for (const f of files) {
                              html += `
                                <tr>
                                  <td>${escapeHtml(f.name ?? "")}</td>
                                  <td>${escapeHtml(f.fileType ?? "")}</td>
                                  <td>${escapeHtml(String(f.size ?? ""))}</td>
                                </tr>
                              `;
                            }
                        
                            html += `</tbody></table>`;
                            area.innerHTML = html;
                          }
                        
                          async function loadTextFile(fileName, targetTextareaId) {
                            clearLog();
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const url = API + "GetTextFile?token=" + encodeURIComponent(base.token) +
                              "&what=" + encodeURIComponent(buildFullPath(fileName));
                        
                            try {
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                              if (data && typeof data.contents !== "undefined") {
                                document.getElementById(targetTextareaId).value = data.contents;
                              } else {
                                alert("לא התקבל תוכן קובץ");
                              }
                            } catch (e) {
                              log("שגיאה בקריאת קובץ טקסט: " + e.message, false);
                            }
                          }
                        
                          async function saveTextFile(fileName, sourceTextareaId) {
                            clearLog();
                            const base = ensureTokenAndPath();
                            if (!base) return;
                        
                            const content = document.getElementById(sourceTextareaId).value;
                        
                            const body = new URLSearchParams();
                            body.append("token", base.token);
                            body.append("what", buildFullPath(fileName));
                            body.append("contents", content);
                        
                            try {
                              const res = await fetch(API + "UploadTextFile", {
                                method: "POST",
                                headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" },
                                body: body.toString()
                              });
                              const data = await safeJson(res);
                              log(data, false);
                              await getDir();
                            } catch (e) {
                              log("שגיאה בשמירת קובץ טקסט: " + e.message, false);
                            }
                          }
                        
                          function loadNamedIni() {
                            const name = document.getElementById("iniFileName").value.trim();
                            if (!name) return alert("נא להזין שם קובץ ini");
                            loadTextFile(name, "iniContent");
                          }
                        
                          function saveNamedIni() {
                            const name = document.getElementById("iniFileName").value.trim();
                            if (!name) return alert("נא להזין שם קובץ ini");
                            saveTextFile(name, "iniContent");
                          }
                        
                          function loadNamedExt() {
                            const name = document.getElementById("extFileName").value.trim();
                            if (!name) return alert("נא להזין שם קובץ ext");
                            loadTextFile(name, "extCustomContent");
                          }
                        
                          function saveNamedExt() {
                            const name = document.getElementById("extFileName").value.trim();
                            if (!name) return alert("נא להזין שם קובץ ext");
                            saveTextFile(name, "extCustomContent");
                          }
                        
                          async function getLists() {
                            clearLog();
                            const token = getToken();
                            if (!token) return alert("נא להזין טוקן");
                        
                            try {
                              const url = API + "?token=" + encodeURIComponent(token) + "&action=getLists";
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                            } catch (e) {
                              log("שגיאה בקבלת רשימות: " + e.message, false);
                            }
                          }
                        
                          async function getListEntries() {
                            clearLog();
                            const token = getToken();
                            const listName = document.getElementById("listName").value.trim();
                            if (!token) return alert("נא להזין טוקן");
                            if (!listName) return alert("נא להזין שם רשימה");
                        
                            try {
                              const url = API + "?token=" + encodeURIComponent(token) +
                                "&action=getlistEnteres&TzintukimList=" + encodeURIComponent(listName);
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                            } catch (e) {
                              log("שגיאה בקבלת מנויי הרשימה: " + e.message, false);
                            }
                          }
                        
                          async function getListLog() {
                            clearLog();
                            const token = getToken();
                            const listName = document.getElementById("listName").value.trim();
                            if (!token) return alert("נא להזין טוקן");
                            if (!listName) return alert("נא להזין שם רשימה");
                        
                            try {
                              const url = API + "?token=" + encodeURIComponent(token) +
                                "&action=getLogList&TzintukimList=" + encodeURIComponent(listName);
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                            } catch (e) {
                              log("שגיאה בקבלת לוג הרשימה: " + e.message, false);
                            }
                          }
                        
                          async function resetList() {
                            clearLog();
                            const token = getToken();
                            const listName = document.getElementById("listName").value.trim();
                            if (!token) return alert("נא להזין טוקן");
                            if (!listName) return alert("נא להזין שם רשימה");
                        
                            if (!confirm("לאפס את הרשימה " + listName + " ?")) return;
                        
                            try {
                              const url = API + "?token=" + encodeURIComponent(token) +
                                "&action=resetList&TzintukimList=" + encodeURIComponent(listName);
                              const res = await fetch(url);
                              const data = await safeJson(res);
                              log(data, false);
                            } catch (e) {
                              log("שגיאה באיפוס רשימה: " + e.message, false);
                            }
                          }
                        
                          function escapeHtml(str) {
                            return String(str)
                              .replaceAll("&", "&amp;")
                              .replaceAll("<", "&lt;")
                              .replaceAll(">", "&gt;")
                              .replaceAll('"', "&quot;")
                              .replaceAll("'", "&#039;");
                          }
                        </script>
                        </body>
                        </html>
                        
                        ל א 2 תגובות תגובה אחרונה תגובה ציטוט 0
                        • ל מנותק
                          לימוד בתורת מרן @לימוד בתורת מרן
                          נערך לאחרונה על ידי

                          @ben-zion
                          מה אומר

                          ל B 2 תגובות תגובה אחרונה תגובה ציטוט 0
                          • ל מנותק
                            לימוד בתורת מרן @לימוד בתורת מרן
                            נערך לאחרונה על ידי

                            יש חדש
                            @ben-zion

                            תגובה 1 תגובה אחרונה תגובה ציטוט 0
                            • א מנותק
                              אA @לימוד בתורת מרן
                              נערך לאחרונה על ידי

                              @לימוד-בתורת-מרן
                              וואו!!!
                              זה ממש הכללל!
                              ודרך אגב יש בתיעוד הסבר איך להוסיף מספרים לרשי"ת.

                              ל תגובה 1 תגובה אחרונה תגובה ציטוט 0
                              • B מנותק
                                BEN ZION @לימוד בתורת מרן
                                נערך לאחרונה על ידי

                                @לימוד-בתורת-מרן יפה אבל אני רוצה משהו יותר מסודר

                                א ל 2 תגובות תגובה אחרונה תגובה ציטוט 0
                                • א מנותק
                                  אA @BEN ZION
                                  נערך לאחרונה על ידי אA

                                  @BEN-ZION
                                  כלומר?
                                  מבחינת העיצוב?
                                  או שהכל יהיה בנוי על רשימת הקבצים המוצגת כמו זה

                                  <!DOCTYPE html>
                                  <html lang="he" dir="rtl">
                                  <head>
                                  <meta charset="UTF-8">
                                  <title>ניהול שלוחות ימות המשיח</title>
                                  <style>
                                  :root {
                                  --primary: #2c3e50; --accent: #3498db; --success: #27ae60;
                                  --danger: #e74c3c; --violet: #8e44ad; --orange: #f39c12;
                                  }
                                  body { font-family: 'Segoe UI', sans-serif; background: #f4f7f6; margin: 0; padding: 20px; }
                                  
                                      /* סרגל עליון */
                                      .top-bar { 
                                          background: white; padding: 15px; border-radius: 10px; 
                                          box-shadow: 0 2px 10px rgba(0,0,0,0.05); display: flex; 
                                          flex-direction: column; gap: 10px; margin-bottom: 20px; 
                                      }
                                      .inputs-row { display: flex; gap: 10px; align-items: center; width: 100%; }
                                      input { padding: 8px; border: 1px solid #ddd; border-radius: 5px; flex: 1; }
                                   
                                      /* עיצוב רכיב הטוקנים */
                                      .token-main { position: relative; flex: 1; display: flex; } /* גודל זהה לשדה הנתיב */
                                      #tokenField { flex: 1; width: 100%; }
                                      
                                      .token-dropdown { 
                                          position: absolute; width: 100%; background: white; border: 1px solid #ccc; 
                                          border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); 
                                          z-index: 1000; max-height: 250px; overflow-y: auto; display: none; top: 100%;
                                      }
                                      .token-item { 
                                          display: flex; justify-content: space-between; align-items: center; 
                                          padding: 10px; cursor: pointer; border-bottom: 1px solid #eee; color: #333;
                                      }
                                      .token-item:hover { background: #f8f9fa; }
                                      .delete-item { color: #dc3545; font-weight: bold; padding: 5px 10px; cursor: pointer; border: none; background: none; }
                                      .dropdown-footer { padding: 8px; background: #f1f3f5; display: flex; gap: 5px; justify-content: center; border-top: 1px solid #ddd; }
                                      .footer-btn { font-size: 11px; padding: 4px 8px; cursor: pointer; border: 1px solid #ccc; background: white; border-radius: 4px; }
                                      
                                      /* כפתורים וטבלה */
                                      .btn { cursor: pointer; border: none; border-radius: 4px; padding: 4px 8px; font-weight: bold; color: white; transition: 0.2s; font-size: 11px; text-align: center; display: inline-block; width: 100%; max-width: 75px; }
                                      .btn:hover { opacity: 0.85; transform: translateY(-1px); }
                                      .btn-load { background: var(--primary); padding: 8px 18px; width: auto; max-width: none; font-size: 14px; }
                                      
                                      .ext-container { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); margin-bottom: 20px; border-top: 4px solid var(--primary); }
                                      .ext-container h4 { margin: 0 0 10px 0; color: var(--primary); display: flex; justify-content: space-between; align-items: center; }
                                      #extTextArea { width: 100%; height: 120px; font-family: 'Consolas', monospace; font-size: 13px; padding: 10px; box-sizing: border-box; border: 1px solid #ddd; background: #fcfcfc; border-radius: 5px; }
                                   
                                      table { width: 100%; background: white; border-collapse: collapse; border-radius: 8px; overflow: hidden; }
                                      th { background: #f8f9fa; padding: 10px; font-size: 12px; border-bottom: 2px solid #eee; }
                                      td { padding: 5px 8px; border-bottom: 1px solid #eee; text-align: center; font-size: 12px; }
                                      
                                      .dl { background: var(--success); } .ed { background: var(--orange); } .up { background: var(--accent); } .del { background: var(--danger); } .view { background: var(--violet); }
                                   
                                      .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); justify-content: center; align-items: center; z-index: 1000; }
                                      .modal-content { background: white; padding: 25px; border-radius: 12px; width: 600px; max-width: 95%; }
                                      .modal-footer { margin-top: 20px; display: flex; justify-content: flex-start; flex-direction: row-reverse; gap: 10px; }
                                      .convert-row { display: flex; gap: 10px; justify-content: center; margin-top: 20px; }
                                  </style>
                                  </head>
                                  <body>
                                  
                                  <div class="top-bar">
                                  <div class="inputs-row">
                                  <div class="token-main">
                                  <input type="text" id="tokenField" placeholder="הזן טוקן או בחר"
                                  onclick="toggleDropdown(true)" oninput="filterDropdown(this.value)" onkeypress="handleEnter(event)" autocomplete="off">
                                  <div id="tokenDropdown" class="token-dropdown"></div>
                                  </div>
                                  
                                      <input type="text" id="pathField" value="" placeholder="נתיב שלוחה" onkeypress="handleEnter(event)">
                                      <button class="btn btn-load" onclick="startProcess()">טען רשימת קבצים</button>
                                  </div>
                                   
                                  <div style="display: flex; align-items: center; gap: 15px; padding-top: 5px;">
                                      <div style="display: flex; align-items: center; gap: 5px;">
                                          <input type="checkbox" id="saveTokenToggle" style="width: auto; cursor: pointer;" 
                                                 onchange="document.getElementById('tokenNameField').style.display = this.checked ? 'block' : 'none'">
                                          <label for="saveTokenToggle" style="font-size: 12px; cursor: pointer; color: #666;">שמור טוקן זה במאגר</label>
                                      </div>
                                      <div id="tokenNameField" style="display:none;">
                                          <input type="text" id="tokenAlias" placeholder="שם למזהה (למשל: המערכת שלי)" style="font-size: 12px; padding: 5px; width: 200px;">
                                      </div>
                                  </div>
                                  </div>
                                  
                                  <div class="ext-container" id="extContainer" style="display:none;">
                                  <h4>
                                  <span>הגדרות שלוחה (ext.ini)</span>
                                  <div style="display:flex; gap:8px;">
                                  <button class="btn" style="background:var(--orange); width:auto; padding:5px 15px;" onclick="renameExtIni()">שנה שם</button>
                                  <button class="btn" style="background:var(--success); width:auto; padding:5px 15px;" onclick="saveExtIni()">שמור שינויים</button>
                                  </div>
                                  </h4>
                                  <textarea id="extTextArea"></textarea>
                                  </div>
                                  
                                  <table>
                                  <thead>
                                  <tr>
                                  <th style="text-align: right; width: 25%;">שם קובץ</th>
                                  <th>גודל</th>
                                  <th>תצוגה</th>
                                  <th>הורדה</th>
                                  <th>שינוי שם</th>
                                  <th>החלפה</th>
                                  <th>מחיקה</th>
                                  </tr>
                                  </thead>
                                  <tbody id="tableBody"></tbody>
                                  </table>
                                  
                                  <div id="mainModal" class="modal">
                                  <div class="modal-content">
                                  <h3 id="modalTitle" style="margin:0 0 15px 0; border-bottom:1px solid #eee; padding-bottom:10px;"></h3>
                                  <div id="modalBody"></div>
                                  <div class="modal-footer" id="modalFooter">
                                  <button id="saveBtn" class="btn btn-load">שמור</button>
                                  <button class="btn" onclick="closeModal()" style="background:#95a5a6;">ביטול</button>
                                  </div>
                                  </div>
                                  </div>
                                  
                                  <script>
                                  const API_BASE = 'https://www.call2all.co.il/ym/api/';
                                  const STORAGE_KEY = 'yemot_permanent_storage';
                                  let savedTokens = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
                                  
                                  document.addEventListener('click', (e) => { if (!e.target.closest('.token-main')) toggleDropdown(false); });
                                  function toggleDropdown(show) {
                                      const dropdown = document.getElementById('tokenDropdown');
                                      if (show) { renderDropdown(); dropdown.style.display = 'block'; }
                                      else { dropdown.style.display = 'none'; }
                                  }
                                  function renderDropdown(filter = "") {
                                      const dropdown = document.getElementById('tokenDropdown');
                                      dropdown.innerHTML = '';
                                      const filteredKeys = Object.keys(savedTokens).filter(a => a.toLowerCase().includes(filter.toLowerCase()));
                                      filteredKeys.forEach(alias => {
                                          const item = document.createElement('div');
                                          item.className = 'token-item';
                                          item.innerHTML = `<span>${alias}</span><button type="button" class="delete-item">✖</button>`;
                                          item.onclick = () => { document.getElementById('tokenField').value = savedTokens[alias]; toggleDropdown(false); };
                                          item.querySelector('.delete-item').onclick = (e) => {
                                              e.stopPropagation();
                                              if(confirm(`למחוק את ${alias}?`)) { 
                                                  delete savedTokens[alias]; 
                                                  localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens)); 
                                                  renderDropdown(filter); 
                                              }
                                          };
                                          dropdown.appendChild(item);
                                      });
                                      const footer = document.createElement('div');
                                      footer.className = 'dropdown-footer';
                                      footer.innerHTML = `<button type="button" class="footer-btn" style="color:red" onclick="if(confirm('למחוק הכל?')){savedTokens={};localStorage.setItem(STORAGE_KEY,'{}');renderDropdown();}">מחק הכל</button>`;
                                      footer.onclick = (e) => e.stopPropagation();
                                      dropdown.appendChild(footer);
                                  }
                                  function filterDropdown(val) { renderDropdown(val); document.getElementById('tokenDropdown').style.display = 'block'; }
                                   
                                  function startProcess() {
                                      saveCurrentTokenIfRequested();
                                      loadDirectory();
                                  }
                                   
                                  function saveCurrentTokenIfRequested() {
                                      const token = document.getElementById('tokenField').value.trim();
                                      const alias = document.getElementById('tokenAlias').value.trim();
                                      if (document.getElementById('saveTokenToggle').checked && alias && token) {
                                          savedTokens[alias] = token;
                                          localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens));
                                      }
                                  }
                                   
                                  function handleEnter(event) { if (event.key === "Enter") startProcess(); }
                                   
                                  function getFullPath(fileName = "") {
                                      let rawPath = document.getElementById('pathField').value.trim();
                                      if (rawPath && !rawPath.endsWith('/') && fileName !== "") rawPath += '/';
                                      return `ivr2:${rawPath}${fileName}`;
                                  }
                                   
                                  async function callApi(method, params = {}) {
                                      const token = document.getElementById('tokenField').value.trim();
                                      if (!token) return;
                                      let url = `${API_BASE}${method}?token=${token}`;
                                      for (let key in params) url += `&${key}=${encodeURIComponent(params[key])}`;
                                      const res = await fetch(url);
                                      return await res.json();
                                  }
                                   
                                  async function loadDirectory() {
                                      const data = await callApi('GetIVR2Dir', { path: getFullPath() });
                                      const body = document.getElementById('tableBody');
                                      body.innerHTML = '';
                                      if (data && data.files) {
                                          data.files.forEach(file => {
                                              const isText = file.name.endsWith('.ini') || file.name.endsWith('.tts');
                                              body.innerHTML += `
                                                  <tr>
                                                      <td style="text-align: right;"><strong>${file.name}</strong></td>
                                                      <td style="color:#888;">${file.size} B</td>
                                                      <td>${isText ? `<button class="btn view" onclick="openTextFile('${file.name}')">הצג</button>` : '-'}</td>
                                                      <td><button class="btn dl" onclick="handleDownloadClick('${file.name}')">הורדה</button></td>
                                                      <td><button class="btn ed" onclick="renameFile('${file.name}')">שינוי</button></td>
                                                      <td><button class="btn up" onclick="uploadUI('${file.name}')">החלפה</button></td>
                                                      <td><button class="btn del" onclick="deleteFile('${file.name}')">מחיקה</button></td>
                                                  </tr>`;
                                          });
                                          loadExtIni();
                                      }
                                  }
                                   
                                  async function loadExtIni() {
                                      const data = await callApi('GetTextFile', { what: getFullPath('ext.ini') });
                                      document.getElementById('extContainer').style.display = 'block';
                                      document.getElementById('extTextArea').value = (data && data.exists !== false) ? data.contents || "" : "קובץ ext.ini לא נמצא.";
                                  }
                                   
                                  async function saveExtIni() {
                                      const res = await callApi('UploadTextFile', { what: getFullPath('ext.ini'), contents: document.getElementById('extTextArea').value });
                                      if (res && res.responseStatus === "OK") alert("נשמר!");
                                  }
                                   
                                  async function renameExtIni() {
                                      const newName = prompt("שם חדש ל-ext.ini:", "ext.ini");
                                      if (newName) {
                                          const res = await callApi('FileAction', { action: 'move', what: getFullPath('ext.ini'), target: getFullPath(newName) });
                                          if (res && res.responseStatus === "OK") loadDirectory();
                                      }
                                  }
                                   
                                  function handleDownloadClick(name) {
                                      if (name.toLowerCase().endsWith('.ymgr')) showConvertModal(name);
                                      else window.open(`${API_BASE}DownloadFile?token=${document.getElementById('tokenField').value}&path=${getFullPath(name)}`);
                                  }
                                   
                                  function showConvertModal(name) {
                                      const html = `
                                          <p style="text-align:center;">בחר פורמט המרה עבור קובץ הנתונים:</p>
                                          <div class="convert-row">
                                              <button class="btn" style="background:var(--primary); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', '')">ללא המרה</button>
                                              <button class="btn" style="background:var(--success); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'csv')">אקסל (CSV)</button>
                                              <button class="btn" style="background:var(--violet); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'html')">דף HTML</button>
                                          </div>`;
                                      showModal("המרה והורדה", html);
                                      document.getElementById('modalFooter').style.display = 'none';
                                  }
                                   
                                  function executeRender(name, type) {
                                      const token = document.getElementById('tokenField').value;
                                      const url = type === "" ? 
                                          `${API_BASE}DownloadFile?token=${token}&path=${getFullPath(name)}` : 
                                          `${API_BASE}RenderYMGRFile?token=${token}&wath=${getFullPath(name)}&convertType=${type}`;
                                      window.open(url);
                                      closeModal();
                                  }
                                   
                                  function showModal(title, html) {
                                      document.getElementById('modalTitle').innerText = title;
                                      document.getElementById('modalBody').innerHTML = html;
                                      document.getElementById('mainModal').style.display = 'flex';
                                      document.getElementById('modalFooter').style.display = 'flex';
                                  }
                                  function closeModal() { document.getElementById('mainModal').style.display = 'none'; }
                                   
                                  async function deleteFile(name) { if (confirm(`למחוק את ${name}?`)) { const res = await callApi('FileAction', { action: 'delete', what: getFullPath(name) }); if (res.responseStatus === "OK") loadDirectory(); } }
                                  function renameFile(name) { const newName = prompt("שם חדש:", name); if (newName) callApi('FileAction', { action: 'move', what: getFullPath(name), target: getFullPath(newName) }).then(loadDirectory); }
                                  async function openTextFile(name) {
                                      const data = await callApi('GetTextFile', { what: getFullPath(name) });
                                      showModal(`עריכת ${name}`, `<textarea id="modalTextArea" style="width:100%; height:300px; font-family:monospace;">${data.contents || ''}</textarea>`);
                                      document.getElementById('saveBtn').onclick = async () => { await callApi('UploadTextFile', { what: getFullPath(name), contents: document.getElementById('modalTextArea').value }); closeModal(); loadDirectory(); };
                                  }
                                  function uploadUI(name) {
                                      showModal(`החלפת ${name}`, `<input type="file" id="fInp" style="margin-top:10px;">`);
                                      document.getElementById('saveBtn').onclick = async () => {
                                          const token = document.getElementById('tokenField').value;
                                          const file = document.getElementById('fInp').files[0];
                                          if (!file) return;
                                          const fd = new FormData(); fd.append('file', file);
                                          await fetch(`${API_BASE}UploadFile?token=${token}&path=${getFullPath()}`, { method: 'POST', body: fd });
                                          closeModal(); loadDirectory();
                                      };
                                  }
                                  </script>
                                  </body>
                                  </html>
                                  
                                  תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                  • ל מנותק
                                    לימוד בתורת מרן @BEN ZION
                                    נערך לאחרונה על ידי

                                    @BEN-ZION
                                    זה ישן לא בדקתי לא סידרתי

                                    תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                    • ל מנותק
                                      לימוד בתורת מרן @אA
                                      נערך לאחרונה על ידי

                                      @אA
                                      יש לך קובץ html
                                      של משהו על api. תוכל לעלות את הקוד
                                      כי כותב שגיאה כי זה בתור html

                                      א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                      • א מנותק
                                        אA @לימוד בתורת מרן
                                        נערך לאחרונה על ידי

                                        @לימוד-בתורת-מרן
                                        ?

                                        B ל 2 תגובות תגובה אחרונה תגובה ציטוט 0
                                        • B מנותק
                                          BEN ZION @אA
                                          נערך לאחרונה על ידי

                                          @אA @לימוד-בתורת-מרן כזה סגנון אני רוצה

                                          תגובה 1 תגובה אחרונה תגובה ציטוט 1
                                          • ל מנותק
                                            לימוד בתורת מרן @אA
                                            נערך לאחרונה על ידי

                                            @אA כתב בפאנל ניהול מותאם אישית:

                                            @לימוד-בתורת-מרן
                                            ?

                                            Screenshot_2026-03-18-21-43-11-532-edit_com.android.chrome.jpg

                                            את זה את הקוד זה קובץ שם
                                            וכותב 404

                                            ל תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                            • פוסט ראשון
                                              פוסט אחרון