<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://shramevjayate.cg.gov.in/</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/screen-reader-access</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/privacy-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/copyright-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/hyperlinking-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/terms-conditions</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/sitemap</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/screen-reader-access</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/privacy-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/copyright-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/hyperlinking-policy</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/terms-conditions</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://shramevjayate.cg.gov.in/shramik/sitemap</loc>
    <lastmod>2026-03-31</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
</urlset>

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>
	Web Portal Upload
</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
  tailwind.config={theme:{extend:{colors:{primary:{50:'#eef2ff',100:'#e0e7ff',200:'#c7d2fe',300:'#a5b4fc',400:'#818cf8',500:'#6366f1',600:'#4f46e5',700:'#4338ca',800:'#3730a3',900:'#312e81'}}}}}
  </script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
  <style>
  .status-dot { animation: pulse 2s infinite; }
  @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }
  .fade-in { animation: fadeIn 0.3s ease; }
  @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
  </style>
  
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" />
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>
  <style>
    /* -- compact icon buttons used across the explorer toolbar / row actions -- */
    .ico {
      display: inline-flex; align-items: center; justify-content: center;
      width: 2rem; height: 2rem; border-radius: .5rem;
      border: 1px solid transparent; transition: background-color .15s, color .15s, border-color .15s;
      font-size: .8rem; line-height: 1;
    }
    .ico:hover { background-color : #f3f4f6; }
    .ico:disabled { opacity: .4; cursor: not-allowed; }
    .ico-on { background-color : #eef2ff; border-color: #c7d2fe; color: #4338ca; }

    /* -- switch -- */
    .switch { position: relative; display: inline-block; width: 2.5rem; height: 1.4rem; }
    .switch input { opacity: 0; width: 0; height: 0; }
    .switch .track {
      position: absolute; inset: 0; cursor: pointer; background: #d1d5db;
      border-radius: 9999px; transition: background-color .2s;
    }
    .switch .track::before {
      content: ""; position: absolute; height: 1.05rem; width: 1.05rem;
      left: .18rem; bottom: .18rem; background: #fff; border-radius: 9999px;
      transition: transform .2s; box-shadow: 0 1px 2px rgba(0,0,0,.25);
    }
    .switch input:checked + .track { background: #10b981; }
    .switch input:checked + .track::before { transform: translateX(1.05rem); }
    .switch input:focus-visible + .track { outline: 2px solid #6366f1; outline-offset: 2px; }

    /* -- file rows -- */
    .frow { transition: background-color .12s; }
    .frow:hover { background-color : #f5f7ff; }
    .frow.is-up { background-color : #fafafa; }
    .frow.is-up:hover { background-color : #f3f4f6; }

    /* -- drop zone -- */
    #dropZone { transition: background-color .15s, border-color .15s, box-shadow .15s; }
    #dropZone.dragging { background-color: #ecfdf5; border-color: #34d399; box-shadow: 0 0 0 4px rgba(52,211,153,.15); }

    /* -- scrollbars inside the file table -- */
    .tbl-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
    .tbl-scroll::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 9999px; border: 3px solid #fff; }
    .tbl-scroll::-webkit-scrollbar-thumb:hover { background: #9ca3af; }

    @media (prefers-reduced-motion: reduce) {
      .frow, .ico, .switch .track, .switch .track::before { transition: none; }
    }
  </style>
</head>
<body class="bg-gray-50">
  <form name="aspnetForm" method="post" action="./WebPortalUpload.aspx?dl=%2fF%3a%2fWebsite%2fcglabour.nic.in%2fshramik%2fpublic%2fsitemap.xml" id="aspnetForm" class="min-h-screen flex flex-col" enctype="multipart/form-data">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTY4NTk2ODUxMQ9kFgJmD2QWAgIDDxYCHgdlbmN0eXBlBRNtdWx0aXBhcnQvZm9ybS1kYXRhFgICAw8WAh4EVGV4dAVoPHNwYW4gY2xhc3M9J2lubGluZS1ibG9jayB3LTIgaC0yIHJvdW5kZWQtZnVsbCBiZy1lbWVyYWxkLTQwMCBzdGF0dXMtZG90JyB0aXRsZT0nU0ZUUCBDb25uZWN0ZWQnPjwvc3Bhbj5kGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYCBSZjdGwwMCRDb250ZW50UGxhY2VIb2xkZXIxJGNoa092ZXJ3cml0ZQUiY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyMSRjaGtVbnppcG+MfBBgZttScQKOY2o+5slWJY7RSo8QFmCnmzbaL8id" />
</div>

<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
    theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
//]]>
</script>


<div>

	<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="D1FA89FA" />
	<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdABEZqbvSZ+gl3gx0Qf18D/VcyEN7b96kbMYHh774BAstdaNmnv639Bo8drXDlaZUJRs0Pg+Tz2JC1nr/M+RFsbAxDTjAMN9jhKqN6BbOBW5ZLKI8BzEMIjiJlSLGQ2nZaCLNzpdySKGvnjdITZwRyOe3DJoSREjQqQQRfvm6NlPGwl/geqyi3kRIkrsa2m1aq8A20P/kGgAojtUrzkaQpZkOjfllUJJkBdSw7wlJDwnpxknPebxRlXiyzm1bViHZ/qdCBn0NdoZ9WQPqrwcPdHqf44dhts8EfjhpZNvmJeu1HGoKkaHInjy2gp8HcO3Ccyj7KK+fBSM3a3HgxtITH/ftcO4LzA+FJdLAqf9UztbPjBBNz8H1P6oaxsZwa/hruCRSan+DvVkCYDgikTNm2K0+" />
</div>

    <!-- â•â•â•â•â•â•â•â•â•â• HEADER : logo + department (left), SFTP status + logout (right) â•â•â•â•â•â•â•â•â•â• -->
    <header class="bg-indigo-800 text-white shadow-md">
      <div class="max-w-[1600px] mx-auto px-4 lg:px-6 py-3 flex items-center gap-4">
        <div class="flex items-center gap-3 min-w-0">
          <img class="h-11 w-11 rounded-lg bg-white p-1 shrink-0" src="Assets/Logo.ashx" alt="Chhattisgarh Government Logo" style="border-width:0px;" />
          <div class="min-w-0">
            <h1 class="text-base sm:text-lg font-bold leading-tight truncate">Labour Department</h1>
            <p class="text-xs text-indigo-200 leading-tight truncate">Government of Chhattisgarh</p>
          </div>
        </div>

        <div class="ml-auto flex items-center gap-2 sm:gap-3 shrink-0">
          <span class="flex items-center gap-2 text-xs sm:text-sm text-indigo-100 bg-indigo-700 border border-indigo-600 rounded-lg px-3 py-1.5">
            <span class='inline-block w-2 h-2 rounded-full bg-emerald-400 status-dot' title='SFTP Connected'></span>
            <span class="hidden sm:inline">SFTP</span>
            <span class="sm:hidden">10.212.194.228</span>
          </span>
          <a href="Login.aspx?logout=1"
            class="flex items-center gap-2 text-sm text-indigo-100 border border-indigo-600 rounded-lg px-3 py-1.5 transition hover:bg-red-600 hover:text-white">
            <i class="fas fa-sign-out-alt"></i>
            <span class="hidden sm:inline">Logout</span>
          </a>
        </div>
      </div>
    </header>

    <main class="flex-1 w-full max-w-[1600px] mx-auto p-4 lg:p-6 fade-in">
      
<div class="w-full">

  <!-- ========== PAGE BAR ========== -->
  <div class="flex flex-wrap items-end justify-between gap-3 mb-4">
    <div class="min-w-0">
      <h2 class="text-xl font-bold text-gray-800 leading-tight">Upload &amp; File Manager</h2>
      <p class="text-sm text-gray-500 mt-0.5">
        Send documents to the SFTP server, and manage what is already stored there.
      </p>
    </div>
    <div class="flex items-center gap-2 shrink-0">
      <span class="inline-flex items-center gap-2 text-xs font-medium text-gray-600 bg-white border border-gray-200 rounded-lg px-3 py-1.5">
        <i class="fas fa-database text-indigo-400"></i>
        
      </span>
    </div>
  </div>

  

  <div class="grid grid-cols-1 xl:grid-cols-4 gap-5 items-start">

    <!-- ========== LEFT : UPLOAD (sticky sidebar) ========== -->
    <div class="xl:col-span-1 xl:sticky xl:top-6">
      <div class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden">

        <div class="px-5 py-4 border-b border-gray-100 flex items-center gap-2.5">
          <span class="w-8 h-8 rounded-lg bg-emerald-50 text-emerald-600 flex items-center justify-center">
            <i class="fas fa-cloud-arrow-up"></i>
          </span>
          <div class="min-w-0">
            <h3 class="text-sm font-bold text-gray-800 leading-tight">Send Files</h3>
            <p class="text-xs text-gray-400 leading-tight">Upload to a folder on the server</p>
          </div>
        </div>

        <div class="p-5">

          <!-- -- Files / Folder switch -- -->
          <div class="inline-flex p-0.5 bg-gray-100 rounded-lg mb-3" role="tablist">
            <button type="button" id="tabFiles" onclick="switchTab('files')"
              class="tab-btn px-3 py-1.5 text-xs font-semibold rounded-md transition">
              <i class="fas fa-file-arrow-up mr-1"></i>Files
            </button>
            <button type="button" id="tabFolder" onclick="switchTab('folder')"
              class="tab-btn px-3 py-1.5 text-xs font-semibold rounded-md transition">
              <i class="fas fa-folder-open mr-1"></i>Folder
            </button>
          </div>

          <!-- -- drop zone -- -->
          <div id="dropZone"
            class="relative border-2 border-dashed border-gray-300 rounded-xl px-4 py-7 text-center">
            <i id="dzIcon" class="fas fa-file-arrow-up text-2xl text-gray-300 mb-2"></i>
            <div id="dzTitle" class="text-sm font-semibold text-gray-700">Drop files here</div>
            <div id="dzHint" class="text-xs text-gray-400 mt-1">
              or <span class="text-emerald-600 font-semibold">browse your computer</span><br />
              <span class="text-[11px]">several files at once</span>
            </div>

            <input type="file" name="ctl00$ContentPlaceHolder1$FileUpload1" id="ctl00_ContentPlaceHolder1_FileUpload1" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer" />
            <input type="file" id="folderInput" name="folderInput" webkitdirectory directory multiple
              class="absolute inset-0 w-full h-full opacity-0 cursor-pointer hidden" />
          </div>

          <!-- -- selection summary -- -->
          <div class="mt-3 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2.5 flex items-center gap-2">
            <i class="fas fa-layer-group text-gray-400 shrink-0"></i>
            <div class="min-w-0 flex-1 text-xs text-gray-600">
              <span id="ctl00_ContentPlaceHolder1_litFileInfo">No files selected yet.</span>
            </div>
            <button type="button" id="clearFiles" onclick="clearFilePickers()"
              class="ico text-gray-400 hover:text-red-600 shrink-0" title="Clear selection">
              <i class="fas fa-xmark"></i>
            </button>
          </div>

          <!-- -- destination -- -->
          <div class="mt-4">
            <label for="ctl00_ContentPlaceHolder1_txtDest" class="block text-xs font-semibold text-gray-600 mb-1.5">
              Destination folder
            </label>
            <div class="relative">
              <i class="fas fa-folder-open absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs"></i>
              <input name="ctl00$ContentPlaceHolder1$txtDest" type="text" value="/" id="ctl00_ContentPlaceHolder1_txtDest" class="w-full border border-gray-300 rounded-lg pl-8 pr-3 py-2 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-emerald-400 focus:border-emerald-400" />
            </div>
            <p class="text-[11px] text-gray-400 mt-1.5 leading-relaxed">
              Accepts a full path such as
              <code class="text-gray-500">/F:/Website/&hellip;/Upload</code>,
              or open that folder in the manager and press
              <span class="font-semibold text-gray-500">Use folder</span>.
            </p>
          </div>

          <!-- -- staged folders (several folders can be queued before uploading) -- -->
          <input type="hidden" id="uploadRelPaths" name="uploadRelPaths" value="" />
          <div id="stageBox" class="hidden mt-3 rounded-lg border border-indigo-100 bg-indigo-50/60 px-3 py-2.5">
            <div class="flex items-center justify-between gap-2 mb-1.5">
              <span class="text-[11px] font-semibold text-indigo-700 uppercase tracking-wide">Queued folders</span>
              <button type="button" onclick="confirmClearFolders()"
                class="text-[11px] font-medium text-indigo-500 hover:text-red-600">clear all</button>
            </div>
            <ul id="stageList" class="space-y-1 max-h-32 overflow-y-auto"></ul>
          </div>

          <!-- -- overwrite switch -- -->
          <div class="mt-4 flex items-center gap-2.5">
            <label class="switch shrink-0">
              <input id="ctl00_ContentPlaceHolder1_chkOverwrite" type="checkbox" name="ctl00$ContentPlaceHolder1$chkOverwrite" checked="checked" />
              <span class="track"></span>
            </label>
            <label for="ctl00_ContentPlaceHolder1_chkOverwrite" class="text-xs text-gray-600 leading-tight cursor-pointer mr-2">
              Replace files
            </label>
            <label class="switch shrink-0">
              <input id="ctl00_ContentPlaceHolder1_chkUnzip" type="checkbox" name="ctl00$ContentPlaceHolder1$chkUnzip" />
              <span class="track"></span>
            </label>
            <label for="ctl00_ContentPlaceHolder1_chkUnzip" class="text-xs text-gray-600 leading-tight cursor-pointer">
              Extract ZIPs
            </label>
          </div>

          <input type="submit" name="ctl00$ContentPlaceHolder1$btnUpload" value="Upload to Server" onclick="if(!syncStaged())return false;var b=this;setTimeout(function(){b.disabled=true;b.innerHTML=&#39;&lt;i class=&quot;fas fa-circle-notch fa-spin&quot;>&lt;/i> Uploading…&#39;;},100);return true;" id="ctl00_ContentPlaceHolder1_btnUpload" class="mt-5 w-full bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 text-white font-semibold text-sm py-2.5 rounded-lg shadow-sm transition flex items-center justify-center gap-2 disabled:opacity-70 disabled:cursor-not-allowed" />

          
        </div>
      </div>
    </div>

    <!-- ========== RIGHT : FILE MANAGER ========== -->
    <div class="xl:col-span-3">
      <div class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden">

        <!-- -- panel head -- -->
        <div class="px-5 py-4 border-b border-gray-100 flex flex-wrap items-center justify-between gap-3">
          <div class="flex items-center gap-2.5 min-w-0">
            <span class="w-8 h-8 rounded-lg bg-indigo-50 text-indigo-600 flex items-center justify-center">
              <i class="fas fa-server"></i>
            </span>
            <div class="min-w-0">
              <h3 class="text-sm font-bold text-gray-800 leading-tight">Server Files</h3>
              <p class="text-xs text-gray-400 leading-tight truncate">
                
              </p>
            </div>
          </div>
          <span class="inline-flex items-center gap-1.5 text-xs font-medium text-indigo-700 bg-indigo-50 border border-indigo-100 rounded-lg px-2.5 py-1">
            <i class="fas fa-sitemap"></i>Copy here with <strong>CPY</strong> &rarr; uploads from this folder
          </span>
        </div>

        <!-- -- toolbar -- -->
        <div class="px-5 py-4 border-b border-gray-100 space-y-3">

          <div id="ctl00_ContentPlaceHolder1_pnlExplorer" onkeypress="javascript:return WebForm_FireDefaultButton(event, &#39;ctl00_ContentPlaceHolder1_btnBrowse&#39;)">
	
            <div class="flex flex-wrap items-center gap-2">
              <div class="relative flex-1 min-w-[220px]">
                <i class="fas fa-folder-open absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs"></i>
                <input name="ctl00$ContentPlaceHolder1$txtPath" type="text" value="/" id="ctl00_ContentPlaceHolder1_txtPath" class="w-full border border-gray-300 rounded-lg pl-8 pr-3 py-2 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:border-indigo-400" />
              </div>
              <input type="submit" name="ctl00$ContentPlaceHolder1$btnBrowse" value="Open" id="ctl00_ContentPlaceHolder1_btnBrowse" class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium px-4 py-2 rounded-lg text-xs transition" />
              <input type="submit" name="ctl00$ContentPlaceHolder1$btnUp" value="↑" id="ctl00_ContentPlaceHolder1_btnUp" title="One level up" class="ico border border-gray-200 text-gray-600 bg-white" />
              <input type="submit" name="ctl00$ContentPlaceHolder1$btnRefresh" value="↻" id="ctl00_ContentPlaceHolder1_btnRefresh" title="Refresh this folder" class="ico border border-gray-200 text-gray-600 bg-white" />
            </div>

            <div class="mt-2.5 flex items-start gap-1.5 text-xs text-gray-500" id="crumbs">
              <i class="fas fa-sitemap text-indigo-400 mt-0.5 shrink-0"></i>
              <div class="break-all leading-relaxed"></div>
            </div>

            
          
</div>

          <div class="flex flex-wrap items-center gap-2 pt-3 border-t border-gray-100">
            <div class="relative flex-1 min-w-[160px]">
              <i class="fas fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs"></i>
              <input type="text" id="txtFilter" placeholder="Filter this folder&hellip;" autocomplete="off"
                class="w-full border border-gray-300 rounded-lg pl-8 pr-3 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-400" />
            </div>

            <button type="button" id="chkAll" onclick="toggleAll()"
              class="ico border border-indigo-200 shrink-0" title="Select every visible row">
              <i class="fas fa-check-double"></i>
            </button>

            <input type="submit" name="ctl00$ContentPlaceHolder1$btnZipSelected" value="ZIP selected" id="ctl00_ContentPlaceHolder1_btnZipSelected" class="inline-flex items-center gap-1.5 bg-violet-600 hover:bg-violet-700 text-white font-medium px-3 py-2 rounded-lg text-xs transition shrink-0" />
            <input type="submit" name="ctl00$ContentPlaceHolder1$btnDeleteSelected" value="Delete selected" onclick="return confirmBulkDelete();" id="ctl00_ContentPlaceHolder1_btnDeleteSelected" class="inline-flex items-center gap-1.5 bg-red-600 hover:bg-red-700 text-white font-medium px-3 py-2 rounded-lg text-xs transition shrink-0" />

            <span class="w-px h-6 bg-gray-200 mx-1 hidden sm:block"></span>

            <div class="flex items-center gap-1.5">
              <input name="ctl00$ContentPlaceHolder1$txtNewFolder" type="text" id="ctl00_ContentPlaceHolder1_txtNewFolder" class="w-40 border border-gray-300 rounded-lg px-3 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-emerald-400" placeholder="New folder name" />
              <input type="submit" name="ctl00$ContentPlaceHolder1$btnNewFolder" value="Create" id="ctl00_ContentPlaceHolder1_btnNewFolder" class="bg-emerald-600 hover:bg-emerald-700 text-white font-medium px-3 py-2 rounded-lg text-xs transition shrink-0" />
            </div>
            <input type="submit" name="ctl00$ContentPlaceHolder1$btnSelectFolder" value="Use folder" id="ctl00_ContentPlaceHolder1_btnSelectFolder" title="Use this folder as the upload destination" class="inline-flex items-center gap-1.5 bg-blue-600 hover:bg-blue-700 text-white font-medium px-3 py-2 rounded-lg text-xs transition shrink-0" />
          </div>

          <div class="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-gray-500">
            <span id="ctl00_ContentPlaceHolder1_litSelection"></span>
            <span id="filterCount" class="text-indigo-500"></span>
          </div>
        </div>

        <!-- -- rename -- -->
        

        <!-- -- file table -- -->
        <div class="px-5 pb-1">
          <div class="tbl-scroll overflow-auto rounded-lg border border-gray-200 max-h-[26rem]">
            <table class="w-full text-sm">
              <thead>
                <tr class="text-left text-white">
                  <th class="sticky top-0 z-10 bg-indigo-700 w-9 px-3 py-2 text-center">
                    <input type="checkbox" id="chkAll" onclick="toggleAll()" class="h-4 w-4 rounded border-indigo-500 text-indigo-600 focus:ring-indigo-400 align-middle" title="Select all visible rows" />
                  </th>
                  <th class="sticky top-0 z-10 bg-indigo-700 px-3 py-2 font-medium">
                    <a id="ctl00_ContentPlaceHolder1_lnkSortName" class="inline-flex items-center gap-1 text-white hover:text-indigo-200 font-medium" CausesRedirect="false" href="javascript:__doPostBack(&#39;ctl00$ContentPlaceHolder1$lnkSortName&#39;,&#39;&#39;)">
                      Name <span class="text-indigo-300 text-[10px]">&#9650;</span>
                    </a>
                  </th>
                  <th class="sticky top-0 z-10 bg-indigo-700 px-3 py-2 font-medium w-24">
                    <a id="ctl00_ContentPlaceHolder1_lnkSortSize" class="inline-flex items-center gap-1 text-white hover:text-indigo-200 font-medium" CausesRedirect="false" href="javascript:__doPostBack(&#39;ctl00$ContentPlaceHolder1$lnkSortSize&#39;,&#39;&#39;)">
                      Size <span class="text-indigo-300 text-[10px]"></span>
                    </a>
                  </th>
                  <th class="sticky top-0 z-10 bg-indigo-700 px-3 py-2 font-medium w-40">
                    <a id="ctl00_ContentPlaceHolder1_lnkSortDate" class="inline-flex items-center gap-1 text-white hover:text-indigo-200 font-medium" CausesRedirect="false" href="javascript:__doPostBack(&#39;ctl00$ContentPlaceHolder1$lnkSortDate&#39;,&#39;&#39;)">
                      Modified <span class="text-indigo-300 text-[10px]"></span>
                    </a>
                  </th>
                  <th class="sticky top-0 z-10 bg-indigo-700 px-3 py-2 font-medium w-36 text-right">Actions</th>
                </tr>
              </thead>
              <tbody>
                
              </tbody>
            </table>
          </div>

        </div>

        <!-- -- legend -- -->
        <div class="px-5 py-3 mt-2 border-t border-gray-100 flex flex-wrap items-center gap-x-4 gap-y-1 text-[11px] text-gray-400">
          <span><i class="fas fa-download text-blue-500 w-4"></i> download file</span>
          <span><i class="fas fa-file-zipper text-violet-500 w-4"></i> download as ZIP</span>
          <span><i class="fas fa-pen text-amber-600 w-4"></i> rename / move</span>
          <span><i class="fas fa-copy text-teal-600 w-4"></i> copy to upload folder</span>
          <span><i class="fas fa-trash-can text-red-500 w-4"></i> delete</span>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
  // ========== picker tabs ==========
  // The two inputs are stacked on top of each other inside the drop zone, so
  // visibility is set with an inline style rather than a Tailwind class: if the
  // utility class is not generated, the folder input stays on top of the file
  // input and every click opens the folder picker instead.
  function setPickerVisible(el, visible) {
    if (!el) return;
    if (visible) {
      el.classList.remove('hidden');
      el.style.display = '';
    } else {
      el.style.display = 'none';
    }
  }

  function switchTab(which) {
    var isFiles = which === 'files';
    var tabF = document.getElementById('tabFiles');
    var tabD = document.getElementById('tabFolder');
    var fileInput = document.getElementById('ctl00_ContentPlaceHolder1_FileUpload1');
    var folderInput = document.getElementById('folderInput');
    var icon = document.getElementById('dzIcon');
    var title = document.getElementById('dzTitle');
    var hint = document.getElementById('dzHint');

    if (tabF) tabF.className = 'tab-btn px-3 py-1.5 text-xs font-semibold rounded-md transition ' + (isFiles ? 'bg-white text-emerald-700 shadow-sm' : 'text-gray-500 hover:text-gray-700');
    if (tabD) tabD.className = 'tab-btn px-3 py-1.5 text-xs font-semibold rounded-md transition ' + (!isFiles ? 'bg-white text-emerald-700 shadow-sm' : 'text-gray-500 hover:text-gray-700');

    setPickerVisible(folderInput, !isFiles);
    setPickerVisible(fileInput, isFiles);

    if (icon) icon.className = (isFiles ? 'fas fa-file-arrow-up' : 'fas fa-folder-open') + ' text-2xl text-gray-300 mb-2';
    if (title) title.textContent = isFiles ? 'Drop files here' : 'Add one or more folders';
    if (hint) hint.innerHTML = isFiles
      ? 'or <span class="text-emerald-600 font-semibold">browse your computer</span><br /><span class="text-[11px]">several files at once</span>'
      : 'or <span class="text-emerald-600 font-semibold">choose a folder</span><br /><span class="text-[11px]">repeat to queue as many as you need</span>';
  }

  // ========== folder staging ==========
  // A browser can only pick one folder at a time, so each folder that is chosen
  // (or dropped) is appended here and the picker is reset. The whole batch is
  // merged into a single multipart request when Upload is pressed.
  var staged = [];

  function stageFolder(fileList) {
    var added = 0;
    for (var i = 0; i < fileList.length; i++) {
      staged.push({ file: fileList[i], rel: fileList[i].webkitRelativePath || fileList[i].name, size: fileList[i].size });
      added++;
    }
    if (added) { renderStage(); refreshFileInfo(); switchTab('folder'); }
    return added;
  }

  // Queueing more than one folder needs the staged files to be merged into a
  // single request, and merging requires DataTransfer. Say so up front instead
  // of failing silently on upload.
  function canQueueManyFolders() {
    return typeof window.DataTransfer === 'function' || typeof window.DataTransfer === 'object';
  }

  // Relative path for a file reached through DataTransferItem.webkitGetAsEntry().
  // entry.fullPath looks like "/TopFolder/Sub/photo.jpg", so it maps straight onto
  // the folder layout that has to be recreated on the server.
  function stageEntry(entry) {
    if (!entry) return Promise.resolve(0);

    if (entry.isFile) {
      return new Promise(function (resolve) {
        entry.file(function (file) {
          var rel = entry.fullPath.replace(/^\//, '');
          staged.push({ file: file, rel: rel || file.name, size: file.size });
          resolve(1);
        }, function () { resolve(0); });
      });
    }

    if (entry.isDirectory) {
      var reader = entry.createReader();
      var all = [];
      var readBatch = function () {
        reader.readEntries(function (batch) {
          if (!batch.length) {
            return Promise.all(all.map(stageEntry)).then(function (counts) {
              return counts.reduce(function (a, b) { return a + b; }, 0);
            });
          }
          Array.prototype.push.apply(all, batch);
          readBatch();
        }, function () { return Promise.all(all.map(stageEntry)).then(function () { return 0; }); });
      };
      return readBatch();
    }
    return Promise.resolve(0);
  }

  function renderStage() {
    var box = document.getElementById('stageBox');
    var list = document.getElementById('stageList');
    if (!box || !list) return;

    // Group by top-level folder so the operator sees "Photos - 12 files" rather
    // than one line per file.
    var order = [];
    var byRoot = {};
    staged.forEach(function (item, idx) {
      var root = item.rel.split('/')[0] || item.file.name;
      if (!byRoot[root]) {
        byRoot[root] = { root: root, files: 0, bytes: 0, idx: [] };
        order.push(byRoot[root]);
      }
      byRoot[root].files++;
      byRoot[root].bytes += item.size;
      byRoot[root].idx.push(idx);
    });

    box.classList.toggle('hidden', order.length === 0);
    list.innerHTML = '';
    order.forEach(function (g) {
      var li = document.createElement('li');
      li.className = 'flex items-center gap-2 text-[11px] text-indigo-800';

      var name = document.createElement('span');
      name.className = 'font-semibold truncate';
      name.textContent = g.root;

      var meta = document.createElement('span');
      meta.className = 'text-indigo-400 shrink-0';
      meta.textContent = g.files + ' file' + (g.files === 1 ? '' : 's') + ', ' + humanSize(g.bytes);

      var rm = document.createElement('button');
      rm.type = 'button';
      rm.className = 'ml-auto shrink-0 text-indigo-300 hover:text-red-600';
      rm.title = 'Remove this folder';
      rm.innerHTML = '<i class="fas fa-xmark"></i>';
      rm.onclick = function () {
        staged = staged.filter(function (it, i) { return g.idx.indexOf(i) < 0; });
        renderStage();
        refreshFileInfo();
      };

      li.appendChild(name);
      li.appendChild(meta);
      li.appendChild(rm);
      list.appendChild(li);
    });
  }

  function clearStagedFolders() {
    staged = [];
    var fi = document.getElementById('folderInput');
    if (fi) fi.value = '';
    var rel = document.getElementById('uploadRelPaths');
    if (rel) rel.value = '';
    renderStage();
    refreshFileInfo();
  }

  // Merge every queued file into the folder input so it posts as one request, and
  // send the matching relative paths in a hidden field, because a File put back
  // into the picker loses its own webkitRelativePath.
  function syncStaged() {
    if (staged.length === 0) return true;

    var folderInput = document.getElementById('folderInput');
    var relField = document.getElementById('uploadRelPaths');
    if (!folderInput) return false;

    if (!canQueueManyFolders()) {
      notify('Cannot queue folders',
        'This browser cannot merge several folders into one upload. Use Chrome or Edge, or upload one folder at a time.',
        'warning');
      return false;
    }

    var dt = new DataTransfer();
    var paths = [];
    for (var i = 0; i < staged.length; i++) {
      try {
        dt.items.add(staged[i].file);
        paths.push(staged[i].rel);
      } catch (err) {
        notify('Cannot queue that folder',
          'A file could not be added to the upload: ' + (err && err.message ? err.message : err),
          'warning');
        return false;
      }
    }

    folderInput.files = dt.files;
    if (folderInput.files && folderInput.files.length !== staged.length) {
      notify('Cannot queue that folder',
        'Only ' + folderInput.files.length + ' of ' + staged.length + ' file(s) could be prepared for upload. Try a smaller selection.',
        'warning');
      return false;
    }
    if (relField) relField.value = paths.join('\n');
    return true;
  }

  // ========== selected-files summary ==========
  function refreshFileInfo() {
    var box = document.getElementById('ctl00_ContentPlaceHolder1_litFileInfo');
    if (!box) return;

    var inputs = [
      document.getElementById('ctl00_ContentPlaceHolder1_FileUpload1'),
      document.getElementById('folderInput')
    ];
    var count = 0, bytes = 0, nested = 0;
    inputs.forEach(function (inp) {
      if (!inp || !inp.files) return;
      for (var i = 0; i < inp.files.length; i++) {
        count++;
        bytes += inp.files[i].size;
        if ((inp.files[i].webkitRelativePath || '').indexOf('/') >= 0) nested++;
      }
    });

    // Queued folders are cleared out of the picker as they are added, so they are
    // counted from the stage instead of from folderInput.files.
    if (staged.length > 0) {
      count += staged.length;
      staged.forEach(function (it) { bytes += it.size; });
    }

    var clear = document.getElementById('clearFiles');
    if (clear) clear.classList.toggle('invisible', count === 0);

    if (count === 0) {
      box.innerHTML = '<span class="text-gray-400">No files selected yet.</span>';
      return;
    }
    var html = '<span class="font-semibold text-gray-700">' + count + ' file' + (count === 1 ? '' : 's') + '</span>'
      + ' &middot; ' + humanSize(bytes);
    if (staged.length > 0)
      html += '<br /><span class="text-gray-400">' + staged.length + ' folder' + (staged.length === 1 ? '' : 's')
        + ' queued &mdash; structure will be recreated</span>';
    else if (nested > 0)
      html += '<br /><span class="text-gray-400">' + nested + ' from folder' + (nested === 1 ? '' : 's')
        + ' &mdash; structure will be recreated</span>';
    box.innerHTML = html;
  }

  function humanSize(b) {
    if (b < 1024) return b + ' B';
    if (b < 1048576) return Math.round(b / 1024.0 * 10) / 10 + ' KB';
    if (b < 1073741824) return Math.round(b / 1048576.0 * 10) / 10 + ' MB';
    return Math.round(b / 1073741824.0 * 10) / 10 + ' GB';
  }

  function clearFilePickers() {
    ['ctl00_ContentPlaceHolder1_FileUpload1', 'folderInput'].forEach(function (id) {
      var el = document.getElementById(id);
      if (el) el.value = '';
    });
    staged = [];
    var rel = document.getElementById('uploadRelPaths');
    if (rel) rel.value = '';
    renderStage();
    refreshFileInfo();
  }

  // ========== instant client-side filter over the current folder ==========
  function applyFilter() {
    var box = document.getElementById('txtFilter');
    var term = (box ? box.value : '').toLowerCase().trim();
    var rows = document.querySelectorAll('#' + 'ctl00_ContentPlaceHolder1_rptFolders' + ' tr[data-name]');
    var shown = 0;
    rows.forEach(function (tr) {
      var match = term === '' || (tr.getAttribute('data-name') || '').toLowerCase().indexOf(term) >= 0;
      tr.style.display = match ? '' : 'none';
      if (match) shown++;
    });
    var note = document.getElementById('filterCount');
    if (note) {
      note.textContent = (term === '' ? '' : shown + ' of ' + rows.length + ' shown') +
        (shown === 0 && rows.length > 0 ? ' &mdash; nothing matches' : '');
    }
    var empty = document.getElementById('emptyFolder');
    if (empty) empty.classList.toggle('hidden', rows.length !== 0);
  }

  // ========== row selection ==========
  function visibleRowBoxes() {
    return Array.prototype.filter.call(
      document.querySelectorAll('input.rowSel'),
      function (cb) { return cb.closest('tr').style.display !== 'none'; }
    );
  }

  function toggleAll() {
    var boxes = visibleRowBoxes();
    var allChecked = boxes.length > 0 && boxes.every(function (cb) { return cb.checked; });
    boxes.forEach(function (cb) { cb.checked = !allChecked; });
    updateSelectionCount();
  }

  function updateSelectionCount() {
    var all = document.querySelectorAll('input.rowSel');
    var checked = document.querySelectorAll('input.rowSel:checked');
    var master = document.getElementById('chkAll');
    if (master) {
      var visible = visibleRowBoxes();
      var visibleChecked = visible.filter(function (cb) { return cb.checked; }).length;
      master.checked = (visible.length > 0 && visibleChecked === visible.length);
      master.title = visibleChecked === visible.length ? 'Clear selection' : 'Select all ' + visible.length + ' visible row(s)';
    }
    var lit = document.getElementById('ctl00_ContentPlaceHolder1_litSelection');
    if (lit) {
      lit.innerHTML = checked.length === 0
        ? 'Nothing selected &mdash; tick rows to send several items at once.'
        : '<strong class="text-indigo-700">' + checked.length + '</strong> of ' + all.length + ' row(s) selected.';
    }
  }

  // ========== confirmations (all SweetAlert modals) ==========
  var SWAL_RED = '#dc2626';
  var SWAL_GREY = '#6b7280';
  var SWAL_INDIGO = '#4f46e5';
  var SWAL_TEAL = '#0d9488';

  // Single place that opens a modal, so every prompt in the app looks the same.
  function ask(opts) {
    var base = {
      showCancelButton: true,
      cancelButtonColor: SWAL_GREY,
      reverseButtons: true,
      focusCancel: true,
      backdrop: 'rgba(15, 23, 42, 0.45)',
      customClass: { popup: 'text-sm' }
    };
    for (var k in opts) { if (Object.prototype.hasOwnProperty.call(opts, k)) base[k] = opts[k]; }

    if (window.Swal) return Swal.fire(base).then(function (r) { return !!r.isConfirmed; });

    // SweetAlert2 could not be fetched from the CDN. Fall back to the browser
    // dialog rather than letting a delete happen with no confirmation at all.
    return Promise.resolve(window.confirm((base.title || '') + (base.text ? '\n\n' + base.text : '')));
  }

  function notify(title, text, icon, color) {
    if (window.Swal) {
      Swal.fire({ title: title, text: text, icon: icon, confirmButtonColor: color || SWAL_INDIGO, customClass: { popup: 'text-sm' } });
    } else {
      window.alert(title + (text ? '\n\n' + text : ''));
    }
  }

  function escapeHtml(s) {
    return (s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  function confirmCopy(btn) {
    if (btn.dataset.confirmed === 'true') return true;
    var dest = document.getElementById('ctl00_ContentPlaceHolder1_txtDest').value;

    ask({
      title: 'Copy this item?',
      html: 'It is copied into the upload destination:<br><code class="px-1 py-0.5 bg-gray-100 rounded">' + escapeHtml(dest) + '</code>'
        + '<br><br><span class="text-gray-500">Folders and large files are copied through this web server, so it can take a while.</span>',
      icon: 'question',
      confirmButtonColor: SWAL_TEAL,
      confirmButtonText: 'Yes, copy it',
      cancelButtonText: 'No, keep it here'
    }).then(function (yes) {
      if (!yes) return;
      btn.dataset.confirmed = 'true';
      btn.click();
    });

    return false;
  }

  function confirmUnzip(btn) {
    if (btn.dataset.confirmed === 'true') return true;
    
    ask({
      title: 'Extract this ZIP here?',
      html: 'Its contents will be unpacked into the current folder.<br><br><span class="text-gray-500">Large ZIP files might take a moment to process over the network.</span>',
      icon: 'question',
      confirmButtonColor: '#c026d3',
      confirmButtonText: 'Yes, extract it',
      cancelButtonText: 'Cancel'
    }).then(function (yes) {
      if (!yes) return;
      btn.dataset.confirmed = 'true';
      btn.click();
    });

    return false;
  }

  function confirmBulkDelete() {
    // Second pass: the .click() below re-enters this handler - let it through.
    if (window.__bulkDelete) { window.__bulkDelete = false; return true; }

    var checked = document.querySelectorAll('input.rowSel:checked');
    var n = checked.length;
    if (n === 0) {
      notify('Nothing selected', 'Tick at least one row first.', 'info');
      return false;
    }

    ask({
      title: 'Delete ' + n + ' item' + (n === 1 ? '' : 's') + '?',
      html: 'They are removed from the SFTP server straight away.<br>'
        + '<span class="text-gray-500">Folders are deleted together with everything inside them, and this cannot be undone.</span>',
      icon: 'warning',
      confirmButtonColor: SWAL_RED,
      confirmButtonText: 'Yes, delete ' + n + ' item' + (n === 1 ? '' : 's'),
      cancelButtonText: 'Keep them'
    }).then(function (yes) {
      if (!yes) return;
      window.__bulkDelete = true;
      document.getElementById('ctl00_ContentPlaceHolder1_btnDeleteSelected').click();
    });

    return false;
  }

  function confirmDoubleDelete(btn, e) {
    if (btn.dataset.confirmed === 'true') return true;
    e.preventDefault();

    ask({
      title: 'Delete this item?',
      text: 'It is removed from the SFTP server. Folders go together with everything inside them.',
      icon: 'warning',
      confirmButtonColor: SWAL_RED,
      confirmButtonText: 'Yes, delete it',
      cancelButtonText: 'No'
    })
      .then(function (yes) {
        if (!yes) return false;
        return ask({
          title: 'Last chance',
          text: 'This action cannot be undone. Delete it now?',
          icon: 'error',
          confirmButtonColor: SWAL_RED,
          confirmButtonText: 'Yes, delete permanently',
          cancelButtonText: 'Keep it'
        });
      })
      .then(function (sure) {
        if (!sure) return;
        btn.dataset.confirmed = 'true';
        btn.click();
      });

    return false;
  }

  function confirmClearFolders() {
    var n = staged.length;
    if (n === 0) return;
    ask({
      title: 'Remove ' + n + ' queued file' + (n === 1 ? '' : 's') + '?',
      text: 'They are taken off the upload list. Nothing on the server is touched.',
      icon: 'question',
      confirmButtonColor: SWAL_INDIGO,
      confirmButtonText: 'Yes, clear them',
      cancelButtonText: 'Keep them'
    }).then(function (yes) {
      if (yes) clearStagedFolders();
    });
  }

  // ========== wiring ==========
  document.addEventListener('DOMContentLoaded', function () {
    var fileInput = document.getElementById('ctl00_ContentPlaceHolder1_FileUpload1');
    var folderInput = document.getElementById('folderInput');
    var dropZone = document.getElementById('dropZone');

    switchTab('files');
    refreshFileInfo();

    // Each folder pick is queued, then the picker is emptied so the next pick
    // is a separate folder rather than a replacement.
    if (folderInput) {
      folderInput.addEventListener('change', function () {
        if (folderInput.files && folderInput.files.length) {
          stageFolder(folderInput.files);
          folderInput.value = '';
        }
      });
    }
    if (fileInput) fileInput.addEventListener('change', refreshFileInfo);

    var filter = document.getElementById('txtFilter');
    if (filter) {
      filter.addEventListener('input', applyFilter);
      filter.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') { filter.value = ''; applyFilter(); }
      });
    }

    // drop zone
    if (dropZone) {
      ['dragenter', 'dragover'].forEach(function (name) {
        dropZone.addEventListener(name, function (e) {
          e.preventDefault(); e.stopPropagation();
          dropZone.classList.add('dragging');
        });
      });
      ['dragleave', 'drop'].forEach(function (name) {
        dropZone.addEventListener(name, function (e) {
          e.preventDefault(); e.stopPropagation();
          dropZone.classList.remove('dragging');
        });
      });
      dropZone.addEventListener('drop', function (e) {
        var dt = e.dataTransfer;
        if (!dt) return;

        // Folders can only be read through webkitGetAsEntry, so walk each one.
        var entries = [];
        if (dt.items && dt.items.length && dt.items[0].webkitGetAsEntry) {
          for (var i = 0; i < dt.items.length; i++) {
            var entry = dt.items[i].webkitGetAsEntry && dt.items[i].webkitGetAsEntry();
            if (entry) entries.push(entry);
          }
        }

        if (entries.length > 0) {
          Promise.all(entries.map(stageEntry)).then(function (counts) {
            var total = counts.reduce(function (a, b) { return a + b; }, 0);
            if (total === 0 && dt.files && dt.files.length) stageFolder(dt.files);
          });
          return;
        }

        if (dt.files && dt.files.length > 0 && fileInput) {
          switchTab('files');
          if (!canQueueManyFolders()) {
            notify('Cannot attach dropped files', 'Use Chrome or Edge to drop files straight onto the page.', 'warning');
            return;
          }
          fileInput.files = dt.files;
          refreshFileInfo();
        }
      });
    }

    // "/" focuses the filter box, as in most file managers
    document.addEventListener('keydown', function (e) {
      if (e.key === '/' && e.target === document.body) {
        e.preventDefault();
        var f = document.getElementById('txtFilter');
        if (f) f.focus();
      }
    });

    applyFilter();
    updateSelectionCount();
  });
</script>

    </main>

  
<script src="/WebPortalUpload/WebResource.axd?d=mU7VyCk8AOsz1Ns2s5N1Ma-vHjhQLN2dZH0w8Q5sI6cJrvJKEZSLwLSwqQqyBOWTgX5Mm2PbblCIHHgLAzOyGjt8OVh_Ygp8QmDgrtK32oc1&amp;t=638901734248157332" type="text/javascript"></script>
</form>
</body>
</html>
