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

    קבצים ותוכנות לשימוש במערכות ימות המשיח

    מתוזמן נעוץ נעול הועבר עזרה הדדית למשתמשים מתקדמים
    91 פוסטים 15 כותבים 2.2k צפיות 10 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • R מנותק
      R.E.T מערכות @אA
      נערך לאחרונה על ידי

      @אA
      סתם ממליץ לך לעלות את כל הקבצי HTML לרשת
      אם אין לך שרת תשתמש בזה של כתר התורה פשוט תכניס את הקוד ותלחץ למטה על יצירת קישור זה פתוח בכל הסינונים

      א תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • א מנותק
        אA @R.E.T מערכות
        נערך לאחרונה על ידי אA

        @R.E.T-מערכות
        האמת שהתכוונתי להעלות לשם את כל הקבצים, אבל רציתי לעשות לפני כן סדר וגם להעלות בצורה של אתר ממש.
        או שאולי עדיף להעלות כל אחד בדף נפרד ולהכניס דף ראשי שישלח אליהם?

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

          @אA מי שרוצה אני מעלה הכל לאתר שלי
          בphp ויותר מסודר בעז"ה בימים הקרובים
          @אa הקישור למעלה מחזיר שגיאה 403

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

            @ezerphone
            אתה עורך את הקודים מחדש או מעלה כמו שהם (בPHP כמובן)?

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

              קובץ לשינוי פרטי הקובץ בהשמעת קבצים

              הקובץ בzip
              שינוי-פרטי-קובץ.zip

              קרדיט: @cubase התותח!

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

                קובץ לפתיחת שלוחת טרוויה

                הקוד

                <!DOCTYPE html>
                <html lang="he" dir="rtl">
                <head>
                    <meta charset="UTF-8">
                    <title>מנהל טריוויה IVR2 - שליטה מלאה</title>
                    <link href="https://fonts.googleapis.com/css2?family=Assistant:wght@400;700&family=Courier+Prime&display=swap" rel="stylesheet">
                    <style>
                        :root { --primary: #1a73e8; --bg: #f8f9fa; --border: #dadce0; --log-bg: #1e1e1e; }
                        body { font-family: 'Assistant', sans-serif; background: var(--bg); margin: 0; padding: 10px; height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
                        .app-wrapper { max-width: 1000px; margin: auto; background: white; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); display: flex; flex-direction: column; max-height: 95vh; width: 100%; }
                        .header { padding: 15px 25px; border-bottom: 2px solid #eee; display: flex; justify-content: space-between; align-items: center; }
                        .scroll-area { padding: 20px; overflow-y: auto; flex-grow: 1; }
                        .grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; }
                        .full { grid-column: span 3; }
                        .half { grid-column: span 1.5; }
                        .field { display: flex; flex-direction: column; }
                        label { font-weight: 700; font-size: 12px; margin-bottom: 4px; color: #555; }
                        input, select { padding: 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; background: #fff; }
                        .btn { padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; }
                        .btn-primary { background: var(--primary); color: white; }
                        .btn-success { background: #1e8e3e; color: white; width: 100%; margin-top: 15px; }
                        #log-area { background: var(--log-bg); color: #00ff00; font-family: 'Courier Prime', monospace; padding: 12px; height: 120px; overflow-y: auto; font-size: 12px; border-top: 4px solid #333; direction: ltr; text-align: left; }
                        .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: 1000; justify-content: center; align-items: center; }
                        .modal-content { background: white; width: 90%; max-width: 800px; border-radius: 12px; padding: 25px; overflow-y: auto; max-height: 90vh; }
                        .section-title { grid-column: span 3; margin-top: 15px; padding: 6px 12px; background: #e8f0fe; color: #1a73e8; font-weight: bold; border-radius: 6px; font-size: 13px; border-right: 4px solid var(--primary); }
                        .hidden { display: none; }
                    </style>
                </head>
                <body>
                
                <div class="app-wrapper">
                    <div class="header">
                        <h2 style="margin:0; font-size: 1.2rem;">מנהל טריוויה IVR2 - הגדרות מלאות</h2>
                        <button id="add-btn" class="btn btn-primary hidden" onclick="openModal()">+ הוספת שאלה</button>
                    </div>
                
                    <div id="login-screen" class="scroll-area">
                        <div class="grid" style="grid-template-columns: 1fr 1fr;">
                            <div class="field"><label>מספר מערכת</label><input type="text" id="user"></div>
                            <div class="field"><label>סיסמה</label><input type="password" id="pass"></div>
                            <div class="field full"><label>נתיב שלוחה</label><input type="text" id="path" value="/1"></div>
                            <button class="btn btn-primary full" onclick="doLogin()">התחבר</button>
                        </div>
                    </div>
                
                    <div id="manage-screen" class="scroll-area hidden">
                        <div class="grid">
                            <div class="section-title">הגדרות ניקוד ונסיונות</div>
                            <div class="field"><label>ניקוד ניסיון 1 (points_1)</label><input type="text" id="trivia_questions_points_1" value="2"></div>
                            <div class="field"><label>ניקוד ניסיון 2 (points_2)</label><input type="text" id="trivia_questions_points_2" value="1"></div>
                            <div class="field"><label>ניסיון אחד בלבד?</label>
                                <select id="trivia_questions_only_once"><option value="no">לא</option><option value="yes">כן (yes)</option></select>
                            </div>
                
                            <div class="section-title">הגדרות השמעה וחשיפה</div>
                            <div class="field"><label>ללא חשיפת תשובה?</label>
                                <select id="trivia_questions_without_reveals_answer"><option value="no">לא</option><option value="yes">כן (yes)</option></select>
                            </div>
                            <div class="field"><label>סדר אקראי?</label>
                                <select id="trivia_questions_random"><option value="no">לא</option><option value="yes">כן (yes)</option></select>
                            </div>
                            <div class="field"><label>דילוג על הסבר?</label>
                                <select id="trivia_questions_no_explanation"><option value="no">לא</option><option value="yes">כן (yes)</option></select>
                            </div>
                
                            <div class="section-title">ניהול זמנים וסיום</div>
                            <div class="field"><label>זמן למענה (שניות)</label><input type="number" id="trivia_questions_time_to_answer" value="15"></div>
                            <div class="field"><label>כמות שאלות למשחק</label><input type="number" id="trivia_questions_total_questions" value="0"></div>
                            <div class="field"><label>סגירת השלוחה בסיום?</label>
                                <select id="trivia_questions_hangup_at_end"><option value="no">לא</option><option value="yes">כן (yes)</option></select>
                            </div>
                
                            <div class="section-title">הגדרות מתקדמות</div>
                            <div class="field"><label>השמעת ניקוד בסיום?</label>
                                <select id="trivia_questions_play_points_at_end"><option value="yes">כן</option><option value="no">לא</option></select>
                            </div>
                            <div class="field"><label>מניעת כפל משחקים?</label>
                                <select id="trivia_questions_once_a_day"><option value="no">לא</option><option value="yes">כן (פעם ביום)</option></select>
                            </div>
                            <div class="field"><label>הקלטת שם מאזין?</label>
                                <select id="trivia_questions_record_name"><option value="no">לא</option><option value="yes">כן</option></select>
                            </div>
                        </div>
                    </div>
                
                    <div id="log-area"><div style="color:#aaa">> המערכת מוכנה לסנכרון.</div></div>
                </div>
                
                <div id="qModal" class="modal">
                    <div class="modal-content">
                        <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">
                            <h3 style="margin:0">הוספת שאלה (תיקייה)</h3>
                            <button class="btn" style="background:#eee" onclick="closeModal()">X</button>
                        </div>
                       
                        <div class="grid" style="grid-template-columns: 1fr 1fr;">
                            <div class="field full"><label>מספר תיקייה</label><input type="text" id="q_folder" placeholder="001"></div>
                            <div class="field full"><label>סוג השאלה</label>
                                <select id="ui_mode" onchange="updateUI()">
                                    <option value="american">אמריקאי (Q, A, B, C, D)</option>
                                    <option value="yes_no">נכון / לא נכון (q_yes / q_no)</option>
                                </select>
                            </div>
                
                            <div id="box-american" class="full grid" style="grid-template-columns: 1fr 1fr;">
                                <div class="field full"><label>שאלה (Q.wav)</label><input type="file" id="f_q"></div>
                                <div class="field"><label>נכונה (A.wav)</label><input type="file" id="f_a"></div>
                                <div class="field"><label>שגויה B</label><input type="file" id="f_b"></div>
                                <div class="field"><label>שגויה C</label><input type="file" id="f_c"></div>
                                <div class="field"><label>שגויה D</label><input type="file" id="f_d"></div>
                            </div>
                
                            <div id="box-yesno" class="full hidden grid" style="grid-template-columns: 1fr;">
                                <div class="field"><label>קובץ הקלטה</label><input type="file" id="f_yn"></div>
                                <div class="field"><label>התשובה הנכונה</label>
                                    <select id="yn_val">
                                        <option value="q_yes">נכון (1)</option>
                                        <option value="q_no">לא נכון (0)</option>
                                    </select>
                                </div>
                            </div>
                           
                            <button class="btn btn-success full" onclick="startUpload()">בצע סנכרון שלוחה ושאלה</button>
                        </div>
                    </div>
                </div>
                
                <script>
                    let token = '';
                    const API = 'https://www.call2all.co.il/ym/api/';
                
                    function addLog(m, e=false) {
                        const div = document.createElement('div');
                        if(e) div.style.color = '#ff5555';
                        div.innerText = `[${new Date().toLocaleTimeString()}] ${m}`;
                        document.getElementById('log-area').appendChild(div);
                        document.getElementById('log-area').scrollTop = document.getElementById('log-area').scrollHeight;
                    }
                
                    async function doLogin() {
                        const u = document.getElementById('user').value, p = document.getElementById('pass').value;
                        try {
                            const r = await fetch(`${API}Login?username=${u}&password=${p}`);
                            const d = await r.json();
                            if (d.responseStatus === 'OK') {
                                token = d.token;
                                addLog("חיבור הצליח.");
                                document.getElementById('login-screen').classList.add('hidden');
                                document.getElementById('manage-screen').classList.remove('hidden');
                                document.getElementById('add-btn').classList.remove('hidden');
                            } else { addLog(d.message, true); }
                        } catch (e) { addLog("שגיאת תקשורת/CORS", true); }
                    }
                
                    function updateUI() {
                        const mode = document.getElementById('ui_mode').value;
                        document.getElementById('box-american').className = (mode === 'american' ? 'full grid' : 'hidden');
                        document.getElementById('box-yesno').className = (mode === 'yes_no' ? 'full grid' : 'hidden');
                    }
                
                    async function startUpload() {
                        const folder = document.getElementById('q_folder').value, root = document.getElementById('path').value, mode = document.getElementById('ui_mode').value;
                        if(!folder) return alert("הזן תיקייה");
                
                        addLog(`בונה ext.ini עם כל ההגדרות...`);
                
                        // יצירת קובץ ה-ext.ini המלא עם כל מה שמופיע ב-Dashboard
                        let ini = `type=trivia_questions\n`;
                        const settings = [
                            'trivia_questions_points_1', 'trivia_questions_points_2', 'trivia_questions_only_once',
                            'trivia_questions_without_reveals_answer', 'trivia_questions_random', 'trivia_questions_no_explanation',
                            'trivia_questions_time_to_answer', 'trivia_questions_total_questions', 'trivia_questions_hangup_at_end',
                            'trivia_questions_play_points_at_end', 'trivia_questions_once_a_day', 'trivia_questions_record_name'
                        ];
                
                        settings.forEach(s => {
                            const val = document.getElementById(s).value;
                            if(val !== 'no' && val !== '0') ini += `${s}=${val}\n`;
                            else if(val === 'no' || val === '0') { /* אפשר להשאיר ריק או לכתוב no לפי הצורך */ }
                        });
                
                        await uploadFile(new Blob([ini], {type:'text/plain'}), root + "/ext.ini");
                
                        // העלאת קבצים
                        if(mode === 'american') {
                            const map = {'Q.wav': 'f_q', 'A.wav': 'f_a', 'B.wav': 'f_b', 'C.wav': 'f_c', 'D.wav': 'f_d'};
                            for(let [file, id] of Object.entries(map)) {
                                const b = document.getElementById(id).files[0];
                                if(b) await uploadFile(b, `${root}/${folder}/${file}`);
                            }
                        } else {
                            const b = document.getElementById('f_yn').files[0];
                            if(b) await uploadFile(b, `${root}/${folder}/${document.getElementById('yn_val').value}.wav`);
                        }
                        addLog(`סיום פעולה בתיקייה ${folder}.`);
                        closeModal();
                    }
                
                    async function uploadFile(blob, rawPath) {
                        const path = 'ivr2:' + (rawPath.startsWith('/') ? rawPath : '/' + rawPath);
                        const fd = new FormData();
                        fd.append('token', token); fd.append('path', path); fd.append('file', blob, path.split('/').pop());
                        try {
                            const r = await fetch(`${API}UploadFile`, {method: 'POST', body: fd});
                            const d = await r.json();
                            if(d.responseStatus === 'OK') addLog(`הועלה בהצלחה: ${path}`);
                        } catch(e) { addLog("שגיאת העלאה", true); }
                    }
                
                    function openModal() { document.getElementById('qModal').style.display = 'flex'; updateUI(); }
                    function closeModal() { document.getElementById('qModal').style.display = 'none'; }
                </script>
                </body>
                </html>
                

                קרדיט:@אa

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

                  קובץ לניתוח נתוני המערכת

                  הקוד

                  <!DOCTYPE html>
                  <html lang="he" dir="rtl">
                  <head>
                      <meta charset="UTF-8">
                      <title>ניתוח נתוני מערכות | v26.3</title>
                      <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
                      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
                      <style>
                          :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; }
                          body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; }
                          header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
                          .logo-box { display: flex; align-items: center; gap: 12px; }
                          .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; }
                          .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); }
                          .config-box { display: flex; gap: 12px; align-items: center; }
                          input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; }
                          .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; }
                          .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); }
                          .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; }
                          .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); }
                          .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; }
                          .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; }
                          .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); }
                          .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; }
                          .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; }
                          table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; }
                          th { text-align: right; padding: 15px; background: #475569; color: white; font-size: 0.85rem; }
                          td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; }
                          tr.clickable { cursor: pointer; }
                          tr.clickable:hover { background: rgba(56, 189, 248, 0.1); }
                          .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; margin-left: 8px; }
                          .bar-fill { height: 100%; background: var(--accent); }
                          .modal-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.85); display: none; justify-content: center; align-items: center; z-index: 1000; }
                          .modal-content { background: var(--card); width: 85%; max-height: 85%; border-radius: 20px; border: 1px solid var(--primary); overflow-y: auto; padding: 30px; position: relative; }
                          .close-modal { position: absolute; top: 20px; left: 20px; color: white; font-size: 2rem; cursor: pointer; }
                          .progress-container { width: 100%; background: #1e293b; height: 6px; display: none; }
                          #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; }
                          .hidden { display: none; }
                          .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; background: #334155; }
                          .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; }
                          .dot.active { background: var(--accent); animation: pulse 2s infinite; }
                          @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
                      </style>
                  </head>
                  <body>
                  
                  <header>
                      <div class="logo-box">
                          <div class="logo-icon"><i class="fas fa-chart-pie"></i></div>
                          <div class="logo-text">ניתוח נתוני מערכות</div>
                          <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div>
                      </div>
                      <div class="config-box">
                          <input type="password" id="apiToken" placeholder="טוקן API">
                          <input type="date" id="startDate">
                          <input type="date" id="endDate">
                          <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button>
                      </div>
                  </header>
                  
                  <div class="progress-container" id="progBar"><div id="progress-fill"></div></div>
                  
                  <div class="nav-tabs">
                      <div class="tab active" onclick="switchTab(event, 'dash-tab')">דאשבורד</div>
                      <div class="tab" onclick="switchTab(event, 'ext-tab')">שלוחות</div>
                      <div class="tab" onclick="switchTab(event, 'play-tab')">השמעות</div>
                      <div class="tab" onclick="switchTab(event, 'users-tab')">מאזינים</div>
                      <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')">לוג</div>
                  </div>
                  
                  <div class="main-content">
                      <div id="dash-tab" class="tab-content">
                          <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;">
                              <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div>
                              <div class="card"><span style="color: #94a3b8">סה"כ דקות האזנה</span><br><span id="stat-min" class="stat-num">0</span></div>
                              <div class="card"><span style="color: #94a3b8">שיחות שהושלמו (סוף קובץ)</span><br><span id="stat-comp" class="stat-num">0</span></div>
                          </div>
                          <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div>
                      </div>
                  
                      <div id="ext-tab" class="tab-content hidden">
                          <div class="control-bar">
                              <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select>
                              <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()">
                          </div>
                          <table id="extTable"><thead><tr><th>שם השלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע</th></tr></thead><tbody></tbody></table>
                      </div>
                  
                      <div id="play-tab" class="tab-content hidden">
                          <div class="control-bar">
                              <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select>
                              <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ..." onkeyup="renderPlays()">
                          </div>
                          <table id="playTable"><thead><tr><th>שם קובץ / שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה</th><th>נטישה</th></tr></thead><tbody></tbody></table>
                      </div>
                  
                      <div id="users-tab" class="tab-content hidden">
                          <div class="control-bar">
                              <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות</option></select>
                              <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון..." onkeyup="renderUsers()">
                          </div>
                          <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table>
                      </div>
                  
                      <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console" style="background:#000; color:#22c55e; padding:20px; height:400px; overflow-y:auto; font-family:monospace;"></div></div></div>
                  </div>
                  
                  <div id="userModal" class="modal-overlay" onclick="closeModal()">
                      <div class="modal-content" onclick="event.stopPropagation()">
                          <span class="close-modal" onclick="closeModal()">&times;</span>
                          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                              <h2 id="modalTitle" style="color: var(--primary); margin:0;"></h2>
                              <select id="modalFilter" onchange="filterModalContent()" style="background: var(--bg); border: 1px solid var(--primary); padding: 5px 15px;">
                                  <option value="all">הכל</option>
                                  <option value="שלוחה">שלוחות בלבד</option>
                                  <option value="השמעה">השמעות בלבד</option>
                              </select>
                          </div>
                          <table id="modalTable">
                              <thead>
                                  <tr>
                                      <th>סוג פעילות</th>
                                      <th>שלוחה/קובץ</th>
                                      <th>זמן שהייה</th>
                                      <th>תאריך</th>
                                  </tr>
                              </thead>
                              <tbody></tbody>
                          </table>
                      </div>
                  </div>
                  
                  <script>
                      const API = "https://www.call2all.co.il/ym/api/";
                      let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0 };
                      let currentModalPhone = "";
                      let dailyChart = null;
                      let autoRefreshTimer = null;
                  
                      function addLog(msg, color = '#22c55e') {
                          const console = document.getElementById('debug-console');
                          if(!console) return;
                          const div = document.createElement('div');
                          div.style.color = color;
                          div.innerText = `[${new Date().toLocaleTimeString()}] ${msg}`;
                          console.appendChild(div);
                      }
                  
                      function cleanExt(val) {
                          if (!val) return "ראשית";
                          let s = val.toString().trim().replace(/^\ufeff/, "");
                          if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית";
                          return s;
                      }
                  
                      function parseSec(t) {
                          if (!t) return 0;
                          if (t.toString().includes(':')) {
                              const p = t.split(':').map(Number);
                              return p.length === 3 ? (p[0]*3600)+(p[1]*60)+p[2] : (p[0]*60)+p[1];
                          }
                          return parseInt(t) || 0;
                      }
                  
                      async function manualStart() {
                          if(autoRefreshTimer) clearInterval(autoRefreshTimer);
                          await startFullAnalysis();
                          document.getElementById('live-dot').classList.add('active');
                          document.getElementById('live-text').innerText = "LIVE (עדכון אוטומטי)";
                          autoRefreshTimer = setInterval(startFullAnalysis, 60000); 
                      }
                  
                      async function startFullAnalysis() {
                          const token = document.getElementById('apiToken').value;
                          const start = document.getElementById('startDate').value;
                          const end = document.getElementById('endDate').value;
                          if (!token) return alert("נא להזין טוקן API");
                  
                          addLog("מתחיל סנכרון נתונים...");
                          dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0 };
                          document.getElementById('progBar').style.display = 'block';
                  
                          const monthStr = start.substring(0, 7); 
                          
                          try {
                              const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${monthStr}.ymgr&convertType=json`);
                              const json = await res.json();
                              if (json.data) {
                                  json.data.forEach(row => {
                                      const extName = cleanExt(row["שלוחה"]);
                                      const phone = row["טלפון"] || "חסוי";
                                      const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                      const date = row["תאריך"] || "";
                                      const time = row["התחלה שעה"] || "";
                                      
                                      if (!dataStore.exts[extName]) dataStore.exts[extName] = { count: 0, sec: 0 };
                                      dataStore.exts[extName].count++;
                                      dataStore.exts[extName].sec += sec;
                                      
                                      dataStore.totalSec += sec;
                                      if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 };
                                      dataStore.users[phone].sec += sec;
                  
                                      dataStore.rawActivity.push({ 
                                          phone, 
                                          type: 'שלוחה', 
                                          name: extName, 
                                          sec: sec + " ש'", 
                                          date: date + " " + time
                                      });
                                  });
                              }
                          } catch(e) { addLog("שגיאה בגישה לקובץ LogFolderEnterExit", "red"); }
                  
                          let dates = [];
                          for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]);
                  
                          for (let day of dates) {
                              updateProgress(dates.indexOf(day)+1, dates.length);
                              try {
                                  const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`);
                                  const json = await res.json();
                                  if (json.data) {
                                      if (!dataStore.daily[day]) dataStore.daily[day] = 0;
                                      json.data.forEach(row => {
                                          const file = row["השמעה"] || "לא ידוע";
                                          const phone = row["טלפון"] || "חסוי";
                                          const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                          const len = parseSec(row["אורך הקובץ"]);
                                          const isEnd = row["נקודת יציאה"] === "סוף";
                                          
                                          dataStore.daily[day]++;
                                          dataStore.totalSec += sec;
                                          if (isEnd) dataStore.completed++;
                  
                                          if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 };
                                          dataStore.users[phone].sec += sec;
                                          dataStore.users[phone].calls++;
                  
                                          if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, pcts: [] };
                                          dataStore.plays[file].count++;
                                          dataStore.plays[file].sec += sec;
                                          dataStore.plays[file].pcts.push(len > 0 ? Math.min(100, Math.round((sec/len)*100)) : 0);
                                          if (!isEnd) dataStore.plays[file].drops++;
                  
                                          dataStore.rawActivity.push({ 
                                              phone, 
                                              type: 'השמעה', 
                                              name: file, 
                                              sec: sec + " ש'", 
                                              date: day + " " + (row["שעה"] || "") 
                                          });
                                      });
                                  }
                              } catch(e) {}
                          }
                          renderUI();
                      }
                  
                      function renderUI() {
                          document.getElementById('progBar').style.display = 'none';
                          document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString();
                          document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString();
                          document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString();
                          renderExts(); renderPlays(); renderUsers(); updateChart();
                          addLog("הנתונים מעודכנים.");
                      }
                  
                      function renderExts() {
                          const sort = document.getElementById('extSort').value;
                          const q = document.getElementById('extSearch').value.toLowerCase();
                          let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d})).filter(i => i.name.toLowerCase().includes(q));
                          items.sort((a,b) => b[sort] - a[sort]);
                          document.querySelector('#extTable tbody').innerHTML = items.map(i => `
                              <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr>
                          `).join('');
                      }
                  
                      function renderPlays() {
                          const sort = document.getElementById('playSort').value;
                          const q = document.getElementById('playSearch').value.toLowerCase();
                          let items = Object.entries(dataStore.plays).map(([name, d]) => {
                              const avg = d.pcts.length ? Math.round(d.pcts.reduce((a,b)=>a+b,0)/d.pcts.length) : 0;
                              const drop = Math.round((d.drops/d.count)*100);
                              return {name, avg, drop, ...d};
                          }).filter(i => i.name.toLowerCase().includes(q));
                          items.sort((a,b) => sort === 'count' ? b.count - a.count : b.avg - a.avg);
                          document.querySelector('#playTable tbody').innerHTML = items.map(i => `
                              <tr><td>${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td>
                              <td><div class="bar-container"><div class="bar-fill" style="width:${i.avg}%"></div></div> ${i.avg}%</td>
                              <td style="color:${i.drop > 50 ? 'var(--danger)' : 'var(--accent)'}">${i.drop}%</td></tr>
                          `).join('');
                      }
                  
                      function renderUsers() {
                          const sortKey = document.getElementById('userSort').value;
                          const q = document.getElementById('userSearch').value;
                          let items = Object.entries(dataStore.users).map(([phone, d]) => ({phone, ...d})).filter(i => i.phone.includes(q));
                          items.sort((a,b) => b[sortKey] - a[sortKey]);
                          document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => `
                              <tr class="clickable" onclick="openUserDetail('${i.phone}')">
                                  <td style="font-weight:bold">${i.phone}</td>
                                  <td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td>
                                  <td>${i.calls}</td>
                                  <td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td>
                              </tr>
                          `).join('');
                      }
                  
                      function openUserDetail(phone) {
                          currentModalPhone = phone;
                          document.getElementById('modalTitle').innerText = `פירוט מאזין: ${phone}`;
                          document.getElementById('modalFilter').value = 'all';
                          filterModalContent();
                          document.getElementById('userModal').style.display = 'flex';
                      }
                  
                      function filterModalContent() {
                          const filter = document.getElementById('modalFilter').value;
                          const activity = dataStore.rawActivity.filter(a => a.phone === currentModalPhone);
                          const filtered = filter === 'all' ? activity : activity.filter(a => a.type === filter);
                  
                          document.querySelector('#modalTable tbody').innerHTML = filtered.map(a => `
                              <tr>
                                  <td style="color:${a.type==='השמעה'?'var(--primary)':'var(--accent)'}; font-weight:bold">${a.type}</td>
                                  <td>${a.name}</td>
                                  <td>${a.sec}</td>
                                  <td>${a.date}</td>
                              </tr>
                          `).join('');
                      }
                  
                      function closeModal() { document.getElementById('userModal').style.display = 'none'; }
                      function updateProgress(c, t) { document.getElementById('progress-fill').style.width = (c/t*100) + '%'; }
                      function switchTab(e, id) {
                          document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
                          document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                          document.getElementById(id).classList.remove('hidden');
                          e.currentTarget.classList.add('active');
                      }
                      function updateChart() {
                          if (dailyChart) dailyChart.destroy();
                          const ctx = document.getElementById('dailyChart').getContext('2d');
                          dailyChart = new Chart(ctx, {
                              type: 'line',
                              data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'שיחות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] },
                              options: { plugins: { legend: { display: false } } }
                          });
                      }
                      document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0];
                  </script>
                  </body>
                  </html>
                  

                  קרדיט: @אa

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

                    עידכון:
                    השרשור עודכן בקבצים חדשים.
                    כל הקבצים בפוסט הראשון.

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

                      @אA אולי כדאי שתפתח פוסט חדש במדריכים עם כל הקבצים, זה קצת איבד כאן את הרצף...
                      תודה רבה על כל הפעילות.

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

                        @בוס
                        קיבלתי.

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

                          @אA את הקודים עצמם תשים בספוילר למניאת גלילה ארוכה ומיותרת, ואם יש שני גרסאות שימושיות של תוכנה כל שהיא אפשר להביא את שניהם ולציין זאת.

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

                            @בוס
                            לא עדיף בקוד להעתקה קלה?

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

                              @אA כן אבל בתוך סופוילר

                              ככה:

                              <!DOCTYPE html>
                              <html lang="he" dir="rtl">
                              <head>
                                  <meta charset="UTF-8">
                                  <title>ניתוח נתוני מערכות | v26.3</title>
                                  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
                                  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
                                  <style>
                                      :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; }
                                      body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; }
                                      header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
                                      .logo-box { display: flex; align-items: center; gap: 12px; }
                                      .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; }
                                      .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); }
                                      .config-box { display: flex; gap: 12px; align-items: center; }
                                      input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; }
                                      .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; }
                                      .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); }
                                      .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; }
                                      .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); }
                                      .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; }
                                      .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; }
                                      .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); }
                                      .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; }
                                      .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; }
                                      table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; }
                                      th { text-align: right; padding: 15px; background: #475569; color: white; font-size: 0.85rem; }
                                      td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; }
                                      tr.clickable { cursor: pointer; }
                                      tr.clickable:hover { background: rgba(56, 189, 248, 0.1); }
                                      .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; margin-left: 8px; }
                                      .bar-fill { height: 100%; background: var(--accent); }
                                      .modal-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.85); display: none; justify-content: center; align-items: center; z-index: 1000; }
                                      .modal-content { background: var(--card); width: 85%; max-height: 85%; border-radius: 20px; border: 1px solid var(--primary); overflow-y: auto; padding: 30px; position: relative; }
                                      .close-modal { position: absolute; top: 20px; left: 20px; color: white; font-size: 2rem; cursor: pointer; }
                                      .progress-container { width: 100%; background: #1e293b; height: 6px; display: none; }
                                      #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; }
                                      .hidden { display: none; }
                                      .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; background: #334155; }
                                      .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; }
                                      .dot.active { background: var(--accent); animation: pulse 2s infinite; }
                                      @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
                                  </style>
                              </head>
                              <body>
                               
                              <header>
                                  <div class="logo-box">
                                      <div class="logo-icon"><i class="fas fa-chart-pie"></i></div>
                                      <div class="logo-text">ניתוח נתוני מערכות</div>
                                      <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div>
                                  </div>
                                  <div class="config-box">
                                      <input type="password" id="apiToken" placeholder="טוקן API">
                                      <input type="date" id="startDate">
                                      <input type="date" id="endDate">
                                      <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button>
                                  </div>
                              </header>
                               
                              <div class="progress-container" id="progBar"><div id="progress-fill"></div></div>
                               
                              <div class="nav-tabs">
                                  <div class="tab active" onclick="switchTab(event, 'dash-tab')">דאשבורד</div>
                                  <div class="tab" onclick="switchTab(event, 'ext-tab')">שלוחות</div>
                                  <div class="tab" onclick="switchTab(event, 'play-tab')">השמעות</div>
                                  <div class="tab" onclick="switchTab(event, 'users-tab')">מאזינים</div>
                                  <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')">לוג</div>
                              </div>
                               
                              <div class="main-content">
                                  <div id="dash-tab" class="tab-content">
                                      <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;">
                                          <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div>
                                          <div class="card"><span style="color: #94a3b8">סה"כ דקות האזנה</span><br><span id="stat-min" class="stat-num">0</span></div>
                                          <div class="card"><span style="color: #94a3b8">שיחות שהושלמו (סוף קובץ)</span><br><span id="stat-comp" class="stat-num">0</span></div>
                                      </div>
                                      <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div>
                                  </div>
                               
                                  <div id="ext-tab" class="tab-content hidden">
                                      <div class="control-bar">
                                          <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select>
                                          <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()">
                                      </div>
                                      <table id="extTable"><thead><tr><th>שם השלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע</th></tr></thead><tbody></tbody></table>
                                  </div>
                               
                                  <div id="play-tab" class="tab-content hidden">
                                      <div class="control-bar">
                                          <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select>
                                          <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ..." onkeyup="renderPlays()">
                                      </div>
                                      <table id="playTable"><thead><tr><th>שם קובץ / שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה</th><th>נטישה</th></tr></thead><tbody></tbody></table>
                                  </div>
                               
                                  <div id="users-tab" class="tab-content hidden">
                                      <div class="control-bar">
                                          <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות</option></select>
                                          <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון..." onkeyup="renderUsers()">
                                      </div>
                                      <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table>
                                  </div>
                               
                                  <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console" style="background:#000; color:#22c55e; padding:20px; height:400px; overflow-y:auto; font-family:monospace;"></div></div></div>
                              </div>
                               
                              <div id="userModal" class="modal-overlay" onclick="closeModal()">
                                  <div class="modal-content" onclick="event.stopPropagation()">
                                      <span class="close-modal" onclick="closeModal()">&times;</span>
                                      <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                                          <h2 id="modalTitle" style="color: var(--primary); margin:0;"></h2>
                                          <select id="modalFilter" onchange="filterModalContent()" style="background: var(--bg); border: 1px solid var(--primary); padding: 5px 15px;">
                                              <option value="all">הכל</option>
                                              <option value="שלוחה">שלוחות בלבד</option>
                                              <option value="השמעה">השמעות בלבד</option>
                                          </select>
                                      </div>
                                      <table id="modalTable">
                                          <thead>
                                              <tr>
                                                  <th>סוג פעילות</th>
                                                  <th>שלוחה/קובץ</th>
                                                  <th>זמן שהייה</th>
                                                  <th>תאריך</th>
                                              </tr>
                                          </thead>
                                          <tbody></tbody>
                                      </table>
                                  </div>
                              </div>
                               
                              <script>
                                  const API = "https://www.call2all.co.il/ym/api/";
                                  let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0 };
                                  let currentModalPhone = "";
                                  let dailyChart = null;
                                  let autoRefreshTimer = null;
                               
                                  function addLog(msg, color = '#22c55e') {
                                      const console = document.getElementById('debug-console');
                                      if(!console) return;
                                      const div = document.createElement('div');
                                      div.style.color = color;
                                      div.innerText = `[${new Date().toLocaleTimeString()}] ${msg}`;
                                      console.appendChild(div);
                                  }
                               
                                  function cleanExt(val) {
                                      if (!val) return "ראשית";
                                      let s = val.toString().trim().replace(/^\ufeff/, "");
                                      if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית";
                                      return s;
                                  }
                               
                                  function parseSec(t) {
                                      if (!t) return 0;
                                      if (t.toString().includes(':')) {
                                          const p = t.split(':').map(Number);
                                          return p.length === 3 ? (p[0]*3600)+(p[1]*60)+p[2] : (p[0]*60)+p[1];
                                      }
                                      return parseInt(t) || 0;
                                  }
                               
                                  async function manualStart() {
                                      if(autoRefreshTimer) clearInterval(autoRefreshTimer);
                                      await startFullAnalysis();
                                      document.getElementById('live-dot').classList.add('active');
                                      document.getElementById('live-text').innerText = "LIVE (עדכון אוטומטי)";
                                      autoRefreshTimer = setInterval(startFullAnalysis, 60000); 
                                  }
                               
                                  async function startFullAnalysis() {
                                      const token = document.getElementById('apiToken').value;
                                      const start = document.getElementById('startDate').value;
                                      const end = document.getElementById('endDate').value;
                                      if (!token) return alert("נא להזין טוקן API");
                               
                                      addLog("מתחיל סנכרון נתונים...");
                                      dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0 };
                                      document.getElementById('progBar').style.display = 'block';
                               
                                      const monthStr = start.substring(0, 7); 
                                      
                                      try {
                                          const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${monthStr}.ymgr&convertType=json`);
                                          const json = await res.json();
                                          if (json.data) {
                                              json.data.forEach(row => {
                                                  const extName = cleanExt(row["שלוחה"]);
                                                  const phone = row["טלפון"] || "חסוי";
                                                  const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                  const date = row["תאריך"] || "";
                                                  const time = row["התחלה שעה"] || "";
                                                  
                                                  if (!dataStore.exts[extName]) dataStore.exts[extName] = { count: 0, sec: 0 };
                                                  dataStore.exts[extName].count++;
                                                  dataStore.exts[extName].sec += sec;
                                                  
                                                  dataStore.totalSec += sec;
                                                  if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 };
                                                  dataStore.users[phone].sec += sec;
                               
                                                  dataStore.rawActivity.push({ 
                                                      phone, 
                                                      type: 'שלוחה', 
                                                      name: extName, 
                                                      sec: sec + " ש'", 
                                                      date: date + " " + time
                                                  });
                                              });
                                          }
                                      } catch(e) { addLog("שגיאה בגישה לקובץ LogFolderEnterExit", "red"); }
                               
                                      let dates = [];
                                      for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]);
                               
                                      for (let day of dates) {
                                          updateProgress(dates.indexOf(day)+1, dates.length);
                                          try {
                                              const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`);
                                              const json = await res.json();
                                              if (json.data) {
                                                  if (!dataStore.daily[day]) dataStore.daily[day] = 0;
                                                  json.data.forEach(row => {
                                                      const file = row["השמעה"] || "לא ידוע";
                                                      const phone = row["טלפון"] || "חסוי";
                                                      const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                      const len = parseSec(row["אורך הקובץ"]);
                                                      const isEnd = row["נקודת יציאה"] === "סוף";
                                                      
                                                      dataStore.daily[day]++;
                                                      dataStore.totalSec += sec;
                                                      if (isEnd) dataStore.completed++;
                               
                                                      if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 };
                                                      dataStore.users[phone].sec += sec;
                                                      dataStore.users[phone].calls++;
                               
                                                      if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, pcts: [] };
                                                      dataStore.plays[file].count++;
                                                      dataStore.plays[file].sec += sec;
                                                      dataStore.plays[file].pcts.push(len > 0 ? Math.min(100, Math.round((sec/len)*100)) : 0);
                                                      if (!isEnd) dataStore.plays[file].drops++;
                               
                                                      dataStore.rawActivity.push({ 
                                                          phone, 
                                                          type: 'השמעה', 
                                                          name: file, 
                                                          sec: sec + " ש'", 
                                                          date: day + " " + (row["שעה"] || "") 
                                                      });
                                                  });
                                              }
                                          } catch(e) {}
                                      }
                                      renderUI();
                                  }
                               
                                  function renderUI() {
                                      document.getElementById('progBar').style.display = 'none';
                                      document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString();
                                      document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString();
                                      document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString();
                                      renderExts(); renderPlays(); renderUsers(); updateChart();
                                      addLog("הנתונים מעודכנים.");
                                  }
                               
                                  function renderExts() {
                                      const sort = document.getElementById('extSort').value;
                                      const q = document.getElementById('extSearch').value.toLowerCase();
                                      let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d})).filter(i => i.name.toLowerCase().includes(q));
                                      items.sort((a,b) => b[sort] - a[sort]);
                                      document.querySelector('#extTable tbody').innerHTML = items.map(i => `
                                          <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr>
                                      `).join('');
                                  }
                               
                                  function renderPlays() {
                                      const sort = document.getElementById('playSort').value;
                                      const q = document.getElementById('playSearch').value.toLowerCase();
                                      let items = Object.entries(dataStore.plays).map(([name, d]) => {
                                          const avg = d.pcts.length ? Math.round(d.pcts.reduce((a,b)=>a+b,0)/d.pcts.length) : 0;
                                          const drop = Math.round((d.drops/d.count)*100);
                                          return {name, avg, drop, ...d};
                                      }).filter(i => i.name.toLowerCase().includes(q));
                                      items.sort((a,b) => sort === 'count' ? b.count - a.count : b.avg - a.avg);
                                      document.querySelector('#playTable tbody').innerHTML = items.map(i => `
                                          <tr><td>${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td>
                                          <td><div class="bar-container"><div class="bar-fill" style="width:${i.avg}%"></div></div> ${i.avg}%</td>
                                          <td style="color:${i.drop > 50 ? 'var(--danger)' : 'var(--accent)'}">${i.drop}%</td></tr>
                                      `).join('');
                                  }
                               
                                  function renderUsers() {
                                      const sortKey = document.getElementById('userSort').value;
                                      const q = document.getElementById('userSearch').value;
                                      let items = Object.entries(dataStore.users).map(([phone, d]) => ({phone, ...d})).filter(i => i.phone.includes(q));
                                      items.sort((a,b) => b[sortKey] - a[sortKey]);
                                      document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => `
                                          <tr class="clickable" onclick="openUserDetail('${i.phone}')">
                                              <td style="font-weight:bold">${i.phone}</td>
                                              <td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td>
                                              <td>${i.calls}</td>
                                              <td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td>
                                          </tr>
                                      `).join('');
                                  }
                               
                                  function openUserDetail(phone) {
                                      currentModalPhone = phone;
                                      document.getElementById('modalTitle').innerText = `פירוט מאזין: ${phone}`;
                                      document.getElementById('modalFilter').value = 'all';
                                      filterModalContent();
                                      document.getElementById('userModal').style.display = 'flex';
                                  }
                               
                                  function filterModalContent() {
                                      const filter = document.getElementById('modalFilter').value;
                                      const activity = dataStore.rawActivity.filter(a => a.phone === currentModalPhone);
                                      const filtered = filter === 'all' ? activity : activity.filter(a => a.type === filter);
                               
                                      document.querySelector('#modalTable tbody').innerHTML = filtered.map(a => `
                                          <tr>
                                              <td style="color:${a.type==='השמעה'?'var(--primary)':'var(--accent)'}; font-weight:bold">${a.type}</td>
                                              <td>${a.name}</td>
                                              <td>${a.sec}</td>
                                              <td>${a.date}</td>
                                          </tr>
                                      `).join('');
                                  }
                               
                                  function closeModal() { document.getElementById('userModal').style.display = 'none'; }
                                  function updateProgress(c, t) { document.getElementById('progress-fill').style.width = (c/t*100) + '%'; }
                                  function switchTab(e, id) {
                                      document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
                                      document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                                      document.getElementById(id).classList.remove('hidden');
                                      e.currentTarget.classList.add('active');
                                  }
                                  function updateChart() {
                                      if (dailyChart) dailyChart.destroy();
                                      const ctx = document.getElementById('dailyChart').getContext('2d');
                                      dailyChart = new Chart(ctx, {
                                          type: 'line',
                                          data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'שיחות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] },
                                          options: { plugins: { legend: { display: false } } }
                                      });
                                  }
                                  document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0];
                              </script>
                              </body>
                              </html>
                              

                              ובשרשור הזה תשנה את הכותרת ל"תגובות על..."

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

                                @בוס

                                גם לך קופץ כל הזמ שהפורום התעדכן לגירסא האחרונה?

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

                                  @אA

                                  קפץ פעם אחת, בפועל לא התשנה משהו הנראה לעין.

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

                                    @בוס

                                    לי כבר קפץ פעמיים, אבל גם בלי שינוי נראה...

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

                                      @אA

                                      תיכף אחד מ"חכמי" הפורום יפתח ע"ז שרשור שלם...

                                      רק לי קפץ התראה על שינוי הפורום...

                                      וכמובן איך אפשק לשכוח, תמונה.

                                      267358c1-7e2f-43b6-a8b7-caba2e9b6a8e-image.png

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