| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928 |
- <!--
- Copyright (C) 2023 Nicola Murino
- This WebUI uses the KeenThemes Mega Bundle, a proprietary theme:
- https://keenthemes.com/products/templates-mega-bundle
- KeenThemes HTML/CSS/JS components are allowed for use only within the
- SFTPGo product and restricted to be used in a resealable HTML template
- that can compete with KeenThemes products anyhow.
- This WebUI is allowed for use only within the SFTPGo product and
- therefore cannot be used in derivative works/products without an
- explicit grant from the SFTPGo Team ([email protected]).
- -->
- {{template "base" .}}
- {{- define "title"}}{{.Title}}{{- end}}
- {{- define "page_body"}}
- {{- template "errmsg" .Error}}
- <div class="card card-flush shadow-sm">
- <div class="card-header pt-8">
- <div class="card-title">
- <div class="d-flex align-items-center position-relative my-1">
- <i class="ki-duotone ki-magnifier fs-1 position-absolute ms-6">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- <input type="text" data-kt-filemanager-table-filter="search" class="form-control form-control-solid w-250px ps-15" placeholder="Search Files & Folders" />
- </div>
- </div>
- <div class="card-toolbar">
- <div class="d-flex justify-content-end" data-kt-filemanager-table-toolbar="base">
- {{- if .CanCreateDirs}}
- <button id="id_create_dir_button" type="button" class="btn btn-flex btn-light-primary me-3">
- <i class="ki-duotone ki-add-folder fs-2">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- New Folder
- </button>
- {{- end}}
- {{- if .CanAddFiles}}
- <button type="button" class="btn btn-flex btn-primary" data-bs-toggle="modal" data-bs-target="#modal_upload">
- <i class="ki-duotone ki-folder-up fs-2">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- Upload Files
- </button>
- {{- end}}
- </div>
- <div class="d-flex justify-content-end align-items-center d-none" data-kt-filemanager-table-toolbar="selected">
- <div class="fw-bold me-5">
- <span class="me-2" data-kt-filemanager-table-select="selected_count"></span>
- </div>
- <div class="form-check form-switch form-check-custom form-check-solid me-5" data-kt-filemanager-table-select="select_all_pages_container">
- <input class="form-check-input" type="checkbox" id="id_select_all_pages" data-kt-filemanager-table-select="select_all_pages" />
- <label class="form-check-label fw-semibold text-gray-900" for="id_select_all_pages">
- Select across pages
- </label>
- </div>
- {{- if or .CanDownload .CanDelete}}
- <div>
- <button type="button" class="btn btn-light-primary rotate" data-kt-menu-trigger="click" data-kt-menu-placement="bottom">
- Actions
- <i class="ki-duotone ki-down fs-3 rotate-180 ms-3 me-0"></i>
- </button>
- <div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-800 menu-state-bg-light-primary fw-semibold w-auto min-w-200 mw-300px py-4" data-kt-menu="true">
- {{- if .CanDownload}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3 fs-6" data-kt-filemanager-table-select="download_selected">
- Download
- </a>
- </div>
- {{- end}}
- {{- if not .ShareUploadBaseURL}}
- {{- if or .CanRename .CanAddFiles}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3 fs-6" data-kt-filemanager-table-select="move_or_copy_selected">
- Move or copy
- </a>
- </div>
- {{- end}}
- {{- if .CanShare}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3 fs-6" data-kt-filemanager-table-select="share_selected">
- Share
- </a>
- </div>
- {{- end}}
- {{- end}}
- {{- if .CanDelete}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3 text-danger fs-6" data-kt-filemanager-table-select="delete_selected">
- Delete
- </a>
- </div>
- {{- end}}
- </div>
- </div>
- {{- end}}
- </div>
- </div>
- </div>
- <div class="card-body">
- <div class="d-flex flex-stack">
- <div class="badge badge-lg badge-light-primary">
- <div class="d-flex align-items-center flex-wrap">
- <i class="ki-duotone ki-home fs-1 text-primary me-3"></i>
- <a href="{{.FilesURL}}?path=%2F">Home</a>
- {{- range .Paths}}
- <i class="ki-duotone ki-right fs-2x text-primary mx-1"></i>
- {{- if eq .Href ""}}
- <span>{{.DirName}}</span>
- {{- else}}
- <a href="{{.Href}}">{{.DirName}}</a>
- {{- end}}
- {{- end}}
- </div>
- </div>
- </div>
- <div id="file_manager_new_folder" class="d-flex align-items-center py-7 d-none">
- <span>
- <i class="ki-duotone ki-folder fs-2x text-primary me-4">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- </span>
- <input id="file_manager_new_folder_input" type="text" name="new_folder_name" placeholder="Enter the new folder name" class="form-control mw-250px me-3" />
- <button class="btn btn-icon btn-light-primary me-3" id="file_manager_add_folder">
- <span class="indicator-label">
- <i class="ki-duotone ki-check fs-1"></i>
- </span>
- <span class="indicator-progress">
- <span class="spinner-border spinner-border-sm align-middle"></span>
- </span>
- </button>
- <button class="btn btn-icon btn-light-danger" id="file_manager_cancel_folder">
- <i class="ki-duotone ki-cross fs-1">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- </button>
- </div>
- <table id="file_manager_list" class="table align-middle table-row-dashed fs-6 gy-5">
- <thead>
- <tr class="text-start text-muted fw-bold fs-6 gs-0">
- <th class="w-10px pe-2">
- <div class="form-check form-check-sm form-check-custom form-check-solid me-3">
- <input id="select_checkbox" class="form-check-input" type="checkbox"/>
- </div>
- </th>
- <th></th>
- <th class="min-w-250px">Name</th>
- <th class="min-w-10px">Size</th>
- <th class="min-w-125px">Last Modified</th>
- <th class="w-125px"></th>
- </tr>
- </thead>
- <tbody id="file_manager_list_body" class="text-gray-700 fw-semibold">
- </tbody>
- </table>
- </div>
- </div>
- {{- end}}
- {{- define "extra_css"}}
- <link href="{{.StaticURL}}/assets/plugins/custom/datatables/datatables.bundle.css" rel="stylesheet" type="text/css"/>
- <link href="{{.StaticURL}}/vendor/glightbox/glightbox.min.css" rel="stylesheet" type="text/css"/>
- <style {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
- .gslide-description-bg {
- background: var(--bs-app-bg-color) !important;
- opacity: 0.9;
- }
- </style>
- {{- end}}
- {{- define "extra_js"}}
- <script src="{{.StaticURL}}/assets/plugins/custom/datatables/datatables.bundle.js"></script>
- <script src="{{.StaticURL}}/vendor/glightbox/glightbox.min.js"></script>
- <script src="{{.StaticURL}}/vendor/pdfobject/pdfobject.min.js"></script>
- <script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
- //{{- if not .ShareUploadBaseURL}}
- const supportedEditExtensions = ["csv", "bat", "dyalog", "apl", "asc", "pgp", "sig", "asn", "asn1", "b", "bf",
- "c", "h", "ino", "cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx", "cob", "cpy", "cbl", "cs", "clj",
- "cljc", "cljx", "cljs", "gss", "cmake", "cmake.in", "coffee", "cl", "lisp", "el", "cyp", "cypher",
- "pyx", "pxd", "pxi", "cr", "css", "cql", "d", "dart", "diff", "patch", "dtd", "dylan", "dyl", "intr",
- "ecl", "edn", "e", "elm", "ejs", "erb", "erl", "sql", "factor", "forth", "fth", "4th", "f", "for", "f77",
- "f90", "f95", "fsharp", "s", "go", "groovy", "gradle", "haml", "hs", "lhs", "hx", "hxml", "aspx",
- "html", "htm", "handlebars", "hbs", "pro", "jade", "pug", "java", "jsp", "js", "json", "map", "jsonld",
- "jsx", "j2", "jinja", "jinja2", "jl", "kt", "less", "ls", "lua", "markdown", "md", "mkd", "m", "nb", "wl",
- "wls", "mo", "mps", "mbox", "nsh", "nsi", "nt", "nq", "m", "mm", "ml", "mli", "mll", "mly", "oz", "p",
- "pas", "pl", "pm", "php", "php3", "php4", "php5", "php7", "phtml", "pig", "txt", "text", "conf", "def",
- "list", "log", "pls", "ps1", "psd1", "psm1", "properties", "ini", "in", "proto", "BUILD", "bzl", "py",
- "pyw", "pp", "q", "r", "rst", "spec", "rb", "rs", "sas", "sass", "scala", "scm", "ss", "scss", "sh",
- "ksh", "bash", "siv", "sieve", "slim", "st", "tpl", "sml", "sig", "fun", "smackspec", "soy", "rq", "sparql",
- "nut", "styl", "swift", "text", "ltx", "tex", "v", "sv", "svh", "tcl", "textile", "toml", "1", "2", "3", "4",
- "5", "6", "7", "8", "9", "ttcn", "ttcn3", "ttcnpp", "cfg", "ttl", "ts", "tsx", "webidl", "vb", "vbs",
- "vtl", "vhd", "vhdl", "vue", "xml", "xsl", "xsd", "svg", "xy", "xquery", "ys", "yaml", "yml", "z80",
- "mscgen", "mscin", "msc", "xu", "msgenny", "wat", "wast"];
- const supportedEditFilenames = ["readme", "dockerfile", "pkgbuild"]
- //{{- end}}
- function keepAlive() {
- //{{- if not .ShareUploadBaseURL}}
- axios.get('{{.PingURL}}',{
- timeout: 15000,
- responseType: 'text'
- }).catch(function (error){});
- //{{- end}}
- }
- //{{- if not .ShareUploadBaseURL}}
- var KTDatatablesFoldersExplorer = function () {
- var dt;
- var curDir;
- var initDatatable = function (dirsURL) {
- $('#errorModalMsg').addClass("d-none");
- dt = $("#dirsbrowser_list").DataTable({
- ajax: {
- url: dirsURL,
- dataSrc: "",
- error: function ($xhr, textStatus, errorThrown) {
- $(".dataTables_processing").hide();
- let txt = "Failed to get directory listing";
- if ($xhr) {
- let json = $xhr.responseJSON;
- if (json) {
- if (json.message) {
- txt += ": " + json.message;
- } else {
- txt += ": " + json.error;
- }
- }
- }
- $('#errorModalTxt').text(txt);
- $('#errorModalMsg').removeClass("d-none");
- }
- },
- deferRender: true,
- processing: true,
- stateSave: false,
- columns: [
- {
- data: "meta"
- },
- {
- data: "name",
- render: function (data, type, row) {
- if (type === 'display') {
- data = escapeHTML(data);
- return `<div class="d-flex align-items-center">
- <i class="ki-duotone ki-folder fs-1 text-primary me-4">
- <i class="path1"></i>
- <i class="path2"></i>
- </i>
- <a href="#" class="text-gray-700 text-hover-primary" data-dirbrowser-table-row="open">${data}</a>
- </div>`
- }
- return data;
- }
- }
- ],
- lengthChange: true,
- columnDefs: [
- {
- targets: 0,
- visible: false,
- searchable: false
- },
- {
- targets: 1,
- visible: true,
- searchable: true
- }
- ],
- language: {
- loadingRecords: "",
- emptyTable: "No more subfolders in here"
- },
- order: [1, 'asc']
- });
- dt.on('draw', function () {
- let dirBrowserNav = document.getElementById("dirs_browser_nav");
- clearChilds(dirBrowserNav);
- let mainNavIcon = document.createElement("i");
- mainNavIcon.classList.add("ki-duotone", "ki-home", "fs-1", "text-primary", "me-3");
- let mainNavLink = document.createElement("a");
- mainNavLink.textContent = "Home";
- mainNavLink.href = "#";
- mainNavLink.addEventListener("click", function(e){
- e.preventDefault();
- onDirBrowserClick("%2F");
- });
- dirBrowserNav.appendChild(mainNavIcon);
- dirBrowserNav.appendChild(mainNavLink);
- let p = "/";
- if (curDir && curDir != "%2F") {
- p = decodeURIComponent(curDir.replace(/\+/g, '%20'));
- const dirPaths = p.split("/");
- let fullPath = "%2F";
- for (idx in dirPaths) {
- let dir = dirPaths[idx];
- if (dir) {
- if (fullPath.endsWith("%2F")){
- fullPath += encodeURIComponent(dir);
- } else {
- fullPath += encodeURIComponent("/" + dir);
- }
- dir = escapeHTML(dir);
- let navIcon = document.createElement("i");
- navIcon.classList.add("ki-duotone", "ki-right", "fs-2x", "text-primary", "mx-1");
- let navLink = document.createElement("a");
- navLink.textContent = dir;
- navLink.href = "#";
- let pathCopy = fullPath
- navLink.addEventListener("click", function(e){
- e.preventDefault();
- onDirBrowserClick(pathCopy);
- });
- dirBrowserNav.appendChild(navIcon);
- dirBrowserNav.appendChild(navLink);
- }
- }
- }
- $('#move_copy_folder').val(p);
- handleRowActions();
- });
- }
- var handleCreateNewFolder = function() {
- $('#dirsbrowser_add_folder').click(function(){
- let errDivEl = $('#errorModalMsg');
- let errTxtEl = $('#errorModalTxt');
- let dirName = replaceSlash($("#dirsbrowser_new_folder_input").val());
- let submitButton = document.querySelector('#dirsbrowser_add_folder');
- let cancelButton = document.querySelector('#dirsbrowser_cancel_folder');
- errDivEl.addClass("d-none");
- if (!dirName){
- errTxtEl.text("Folder name is required");
- errDivEl.removeClass("d-none");
- return;
- }
- let path = '{{.DirsURL}}?path='+ curDir + encodeURIComponent("/"+dirName);
- submitButton.setAttribute('data-kt-indicator', 'on');
- submitButton.disabled = true;
- cancelButton.disabled = true;
- axios.post(path, null, {
- timeout: 15000,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 201;
- }
- }).then(function (response) {
- dt.ajax.reload();
- errDivEl.addClass("d-none");
- submitButton.removeAttribute('data-kt-indicator');
- submitButton.disabled = false;
- cancelButton.disabled = false;
- $('#dirsbrowser_new_folder').addClass("d-none");
- }).catch(function (error) {
- let errorMessage = "Unable to create the new folder";
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- submitButton.removeAttribute('data-kt-indicator');
- submitButton.disabled = false;
- cancelButton.disabled = false;
- });
- });
- }
- function handleRowActions(){
- const openLinks = document.querySelectorAll('[data-dirbrowser-table-row="open"]');
- openLinks.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- onDirBrowserClick(dt.row(parent).data()['dir_path']);
- });
- });
- }
- return {
- init: function (url, dirPath) {
- curDir = dirPath;
- if (dt) {
- dt.ajax.url(url).load();
- return;
- }
- initDatatable(url);
- handleCreateNewFolder();
- }
- }
- }();
- //{{- end}}
- </script>
- <script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
- var KTDatatablesServerSide = function () {
- // Shared variables
- //var table;
- var dt;
- var lightbox;
- // Private functions
- var initDatatable = function () {
- $('#errorMsg').addClass("d-none");
- dt = $("#file_manager_list").DataTable({
- ajax: {
- url: "{{.DirsURL}}?path={{.CurrentDir}}",
- dataSrc: "",
- error: function ($xhr, textStatus, errorThrown) {
- $(".dataTables_processing").hide();
- let txt = "Failed to get directory listing";
- if ($xhr) {
- let json = $xhr.responseJSON;
- if (json) {
- if (json.message){
- txt += ": " + json.message;
- } else {
- txt += ": " + json.error;
- }
- }
- }
- $('#errorTxt').text(txt);
- $('#errorMsg').removeClass("d-none");
- }
- },
- deferRender: true,
- processing: true,
- lengthMenu: [ 10, 25, 50, 100, 250, 500 ],
- select: {
- style: 'multi',
- selector: 'td:first-child input[type="checkbox"]',
- className: 'row-selected'
- },
- stateSave: true,
- stateDuration: 0,
- stateSaveParams: function (settings, data) {
- data.sftpgo_dir = '{{.CurrentDir}}';
- },
- stateLoadParams: function (settings, data) {
- if (!data.sftpgo_dir || data.sftpgo_dir != '{{.CurrentDir}}'){
- data.start = 0;
- data.search.search = "";
- }
- if (data.search.search){
- const filterSearch = document.querySelector('[data-kt-filemanager-table-filter="search"]');
- filterSearch.value = data.search.search;
- }
- },
- columns: [
- {
- data: "meta",
- render: function (data, type) {
- if (type == 'display'){
- return `
- <div class="form-check form-check-sm form-check-custom form-check-solid">
- <input class="form-check-input" type="checkbox" />
- </div>`;
- }
- return data;
- }
- },
- { data: "type" },
- {
- data: "name",
- render: function (data, type, row) {
- if (type === 'display') {
- data = escapeHTML(data);
- let icon_name = "ki-file";
- if (row["type"] == "1") {
- icon_name = "ki-folder";
- } else if (row["size"] === "") {
- icon_name = "ki-file-right"
- }
- return `<div class="d-flex align-items-center">
- <i class="ki-duotone ${icon_name} fs-2x text-primary me-4">
- <i class="path1"></i>
- <i class="path2"></i>
- </i>
- <a href="${row['url']}" class="text-gray-800 text-hover-primary">${data}</a>
- </div>`
- }
- return data;
- }
- },
- {
- data: "size",
- render: function (data, type) {
- if (type === 'display') {
- if (data || data === 0){
- return fileSizeIEC(data);
- }
- return "";
- }
- return data;
- }
- },
- { data: "last_modified" },
- {
- data: "edit_url",
- className: 'text-end',
- render: function (data, type, row) {
- if (type === 'display') {
- let previewDiv = "";
- if (row["type"] == "2") {
- let filename = escapeHTML(row["name"]);
- let extension = filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
- switch (extension) {
- case "jpeg":
- case "jpg":
- case "png":
- case "gif":
- case "webp":
- case "bmp":
- case "svg":
- case "ico":
- let desc = escapeHTML(filename).replace(/"/g, '"');
- previewDiv = `<div class="ms-2" data-kt-filemanger-table="view_item">
- <a href="${row['url']}" data-gallery="gallery" data-glightbox="description: <span class="fs-5 fw-bold">${desc}</span>" class="btn btn-sm btn-icon btn-light btn-active-light-primary glightbox">
- <i class="ki-duotone ki-eye fs-5 m-0">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- </i>
- </a>
- </div>`;
- break;
- case "mp4":
- case "mov":
- case "webm":
- case "ogv":
- case "ogg":
- case "mp3":
- case "wav":
- previewDiv = `<div class="ms-2" data-kt-filemanger-table="view_item">
- <a href="#" class="btn btn-sm btn-icon btn-light btn-active-light-primary" data-kt-filemanager-table-action="view_media">
- <i class="ki-duotone ki-eye fs-5 m-0">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- </i>
- </a>
- </div>`;
- break;
- case "pdf":
- if (PDFObject.supportsPDFs){
- let view_url = row['url'];
- view_url = view_url.replace('{{.FilesURL}}','{{.ViewPDFURL}}');
- previewDiv = `<div class="ms-2" data-kt-filemanger-table="view_item">
- <a href="${view_url}" target="_blank" class="btn btn-sm btn-icon btn-light btn-active-light-primary">
- <i class="ki-duotone ki-eye fs-5 m-0">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- </i>
- </a>
- </div>`;
- }
- break;
- default:
- //{{- if not .ShareUploadBaseURL}}
- if (data && (supportedEditExtensions.includes(extension) || supportedEditFilenames.includes(filename.toLowerCase()))){
- previewDiv = `<div class="ms-2" data-kt-filemanger-table="view_item">
- <a href="${data}" target="_blank" class="btn btn-sm btn-icon btn-light btn-active-light-primary">
- <i class="ki-duotone ki-eye fs-5 m-0">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- </i>
- </a>
- </div>`;
- }
- //{{- end}}
- }
- }
- let more = `{{- if not .ShareUploadBaseURL}}
- {{- if or .CanRename .CanAddFiles .CanShare .CanDelete }}
- <div class="ms-2">
- <button type="button" class="btn btn-sm btn-icon btn-light btn-active-light-primary" data-kt-menu-trigger="click" data-kt-menu-placement="bottom-end">
- <i class="ki-duotone ki-dots-square fs-5 m-0">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- <span class="path4"></span>
- </i>
- </button>
- <div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-700 menu-state-bg-light-primary fw-semibold fs-7 w-150px py-4" data-kt-menu="true">
- {{- if .CanRename}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3" data-kt-filemanager-table-action="rename">Rename</a>
- </div>
- {{- end}}
- {{- if or .CanRename .CanAddFiles}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3" data-kt-filemanager-table-action="move_or_copy">Move or copy</a>
- </div>
- {{- end}}
- {{- if .CanShare}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link px-3" data-kt-filemanager-table-action="share">Share</a>
- </div>
- {{- end}}
- {{- if .CanDelete}}
- <div class="menu-item px-3">
- <a href="#" class="menu-link text-danger px-3" data-kt-filemanager-table-action="delete">Delete</a>
- </div>
- {{- end}}
- </div>
- </div>
- {{- end}}
- {{- end}}`;
- return `<div class="d-flex justify-content-end">
- ${previewDiv}
- ${more}
- </div>
- `;
- }
- return "";
- }
- }
- ],
- lengthChange: true,
- columnDefs: [
- {
- targets: 0,
- orderable: false,
- searchable: false,
- },
- {
- targets: 1,
- visible: false,
- searchable: false
- },
- {
- targets: 2,
- visible: true,
- searchable: true
- },
- {
- targets: [3,4],
- searchable: false
- },
- {
- targets: 5,
- orderable: false,
- searchable: false
- }
- ],
- language: {
- loadingRecords: "",
- emptyTable: "No files or folders"
- },
- orderFixed: [1, 'asc'],
- order: [2, 'asc']
- });
- //table = dt.$;
- dt.on('draw', function () {
- lightbox.reload();
- KTMenu.createInstances();
- let targets = document.querySelectorAll('#file_manager_list_body tr');
- if (targets) {
- KTUtil.each(targets, function (target) {
- if (!target){
- return;
- }
- let checkbox = target.querySelector('.form-check-input');
- if (!checkbox) {
- return;
- }
- if (target.classList.contains('row-selected')) {
- checkbox.checked = true;
- } else {
- checkbox.checked = false;
- }
- });
- }
- toggleToolbars();
- handleRowActions();
- });
- dt.on('user-select', function(e, dt, type, cell, originalEvent){
- let pageSelected = dt.rows({ selected: true, page: 'current' }).count();
- let totalSelected = dt.rows({ selected: true, search: 'applied' }).count();
- if (totalSelected > pageSelected){
- let currentIndexes = [];
- dt.rows({ page: 'current' }).every(function (rowIdx, tableLoop, rowLoop){
- currentIndexes.push(rowIdx);
- });
- dt.rows().deselect();
- currentIndexes.forEach((idx) => {
- dt.row(idx).select();
- });
- totalSelected = dt.rows({ selected: true, search: 'applied' }).count();
- }
- if ($(originalEvent.target).is(':checked')){
- pageSelected++;
- totalSelected++;
- } else {
- pageSelected--;
- totalSelected--;
- }
- handleToogleToolbar(pageSelected, totalSelected);
- });
- }
- function handleToogleToolbar(pageSelected, totalSelected) {
- const toolbarBase = document.querySelector('[data-kt-filemanager-table-toolbar="base"]');
- const toolbarSelected = document.querySelector('[data-kt-filemanager-table-toolbar="selected"]');
- const selectedCount = document.querySelector('[data-kt-filemanager-table-select="selected_count"]');
- const selectAllContainer = document.querySelector('[data-kt-filemanager-table-select="select_all_pages_container"]');
- const selectAllCheck = document.querySelector('[data-kt-filemanager-table-select="select_all_pages"]');
- if (pageSelected > 0) {
- let pageTotal = dt.rows({ page: 'current' }).count();
- if (pageSelected === pageTotal){
- selectAllContainer.classList.remove("d-none");
- $('#select_checkbox').prop("checked", true);
- } else {
- $('#select_checkbox').prop("checked", false);
- selectAllCheck.checked = false;
- selectAllContainer.classList.add('d-none');
- }
- if (selectedCount){
- selectedCount.innerHTML = `${totalSelected} Selected`;
- }
- if (toolbarBase){
- toolbarBase.classList.add('d-none');
- }
- if (toolbarSelected){
- toolbarSelected.classList.remove('d-none');
- }
- } else {
- $('#select_checkbox').prop("checked", false);
- selectAllCheck.checked = false;
- if (toolbarBase) {
- toolbarBase.classList.remove('d-none');
- }
- if (toolbarBase) {
- toolbarSelected.classList.add('d-none');
- }
- }
- }
- function handleRowActions() {
- const renameButtons = document.querySelectorAll('[data-kt-filemanager-table-action="rename"]');
- renameButtons.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- renameItem(dt.row(parent).data()["meta"]);
- });
- });
- const moveCopyButtons = document.querySelectorAll('[data-kt-filemanager-table-action="move_or_copy"]');
- moveCopyButtons.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- moveOrCopyItem(dt.row(parent).data()["meta"]);
- });
- });
- const shareButtons = document.querySelectorAll('[data-kt-filemanager-table-action="share"]');
- shareButtons.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- shareItem(dt.row(parent).data()["meta"]);
- });
- });
- const deleteButtons = document.querySelectorAll('[data-kt-filemanager-table-action="delete"]');
- deleteButtons.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- deleteItem(dt.row(parent).data()["meta"]);
- });
- });
- const viewMediaLinks = document.querySelectorAll('[data-kt-filemanager-table-action="view_media"]');
- viewMediaLinks.forEach(d => {
- d.addEventListener("click", function(e){
- e.preventDefault();
- const parent = e.target.closest('tr');
- let rowData = dt.row(parent).data();
- openMediaPlayer(rowData["name"], rowData["url"]);
- });
- });
- }
- var initLightbox = function() {
- lightbox = GLightbox({
- slideHTML: `<div class="gslide">
- <div class="gslide-inner-content">
- <div class="ginner-container">
- <div class="gslide-media">
- </div>
- <div class="gslide-description gslide-description-bg">
- <div class="gdesc-inner">
- <h4 class="gslide-title"></h4>
- <div class="gslide-desc"></div>
- </div>
- </div>
- </div>
- </div>
- </div>`,
- preload: false,
- closeOnOutsideClick: false
- });
- }
- var handleSearchDatatable = function () {
- const filterSearch = document.querySelector('[data-kt-filemanager-table-filter="search"]');
- filterSearch.addEventListener('keyup', function (e) {
- dt.rows().deselect();
- dt.search(e.target.value, true, false).draw();
- });
- }
- var initToggleToolbar = function () {
- const selectAllCheck = document.querySelector('[data-kt-filemanager-table-select="select_all_pages"]');
- if (selectAllCheck){
- selectAllCheck.addEventListener('change', function(e){
- if (this.checked){
- dt.rows({ search: 'applied' }).select();
- } else {
- let selectedIndexes = [];
- dt.rows({ selected: true, page: 'current' }).every(function (rowIdx, tableLoop, rowLoop){
- selectedIndexes.push(rowIdx);
- });
- dt.rows().deselect();
- selectedIndexes.forEach((idx) => {
- dt.row(idx).select();
- });
- }
- toggleToolbars();
- })
- }
- const downloadButton = document.querySelector('[data-kt-filemanager-table-select="download_selected"]');
- if (downloadButton){
- downloadButton.addEventListener('click', function(e){
- let filesArray = [];
- dt.rows({ selected: true, search: 'applied' }).every(function (rowIdx, tableLoop, rowLoop){
- let row = dt.row(rowIdx);
- filesArray.push(getNameFromMeta(row.data()['meta']));
- });
- let token = "{{.CSRFToken}}";
- let downloadURL = '{{.DownloadURL}}';
- let currentDir = '{{.CurrentDir}}';
- let ts = new Date().getTime().toString();
- let files = JSON.stringify(filesArray);
- $(`<form method="post" action="${downloadURL}?path=${currentDir}&_=${ts}" target="_blank">
- <input type="hidden" name="_form_token" value="${token}">
- <textarea name="files" hidden>${files}</textarea>
- </form>`).appendTo('body').submit().remove();
- });
- }
- const moveOrCopyButton = document.querySelector('[data-kt-filemanager-table-select="move_or_copy_selected"]');
- if (moveOrCopyButton){
- moveOrCopyButton.addEventListener('click', function(e){
- $('#errorMsg').addClass("d-none");
- $('#move_copy_name_container').addClass("d-none");
- $('#move_copy_source').val("");
- $('#modal_move_or_copy').modal('show');
- KTDatatablesFoldersExplorer.init('{{.DirsURL}}?dirtree=1&path={{.CurrentDir}}', '{{.CurrentDir}}');
- });
- }
- const shareButton = document.querySelector('[data-kt-filemanager-table-select="share_selected"]');
- if (shareButton){
- shareButton.addEventListener('click', function(e){
- let filesArray = [];
- dt.rows({ selected: true, search: 'applied' }).every(function (rowIdx, tableLoop, rowLoop){
- let row = dt.row(rowIdx);
- filesArray.push(getNameFromMeta(row.data()['meta']));
- });
- let files = encodeURIComponent(JSON.stringify(filesArray));
- let shareURL = '{{.ShareURL}}';
- let currentDir = '{{.CurrentDir}}';
- let ts = new Date().getTime().toString();
- window.open(`${shareURL}?path=${currentDir}&files=${files}&_=${ts}`,'_blank');
- });
- }
- const deleteButton = document.querySelector('[data-kt-filemanager-table-select="delete_selected"]');
- if (deleteButton) {
- deleteButton.addEventListener('click', function(e){
- ModalAlert.fire({
- text: "Do you want to delete the selected item/s? This action is irreversible",
- icon: "warning",
- confirmButtonText: "Delete",
- cancelButtonText: 'Cancel',
- customClass: {
- confirmButton: "btn btn-danger",
- cancelButton: 'btn btn-secondary'
- }
- }).then((result) => {
- if (result.isConfirmed){
- let hasError = false;
- let deleted = 0;
- let index = 0;
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- errDivEl.addClass("d-none");
- let selectedRowsIdx = [];
- dt.rows({ selected: true, search: 'applied' }).every(function (rowIdx, tableLoop, rowLoop){
- selectedRowsIdx.push(rowIdx);
- });
- if (selectedRowsIdx.length == 0){
- return;
- }
- keepAlive();
- let keepAliveTimer = setInterval(keepAlive, 300000);
- $('#loading_message').text("");
- KTApp.showPageLoading();
- function deleteSelected() {
- if (index >= selectedRowsIdx.length || hasError){
- clearInterval(keepAliveTimer);
- KTApp.hidePageLoading();
- if (!hasError){
- location.reload();
- }
- return;
- }
- let meta = dt.row(selectedRowsIdx[index]).data()['meta'];
- let attrs = getDeleteReqAttrs(meta);
- let deleteTxt = "";
- if (selectedRowsIdx.length > 1){
- let name = getNameFromMeta(meta);
- deleteTxt = `Delete ${index+1}/${selectedRowsIdx.length}: ${name}`;
- }
- $('#loading_message').text(deleteTxt);
- axios.delete(attrs.path,{
- timeout: attrs.reqTimeout,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 200;
- }
- }).then(function(response){
- index++;
- deleted++;
- deleteSelected();
- }).catch(function(error){
- index++;
- hasError = true;
- let errorMessage = "Unable to delete the selected item/s";
- if (deleted > 0){
- errorMessage = "Not all the selected items have been deleted, please reload the page";
- }
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- deleteSelected();
- });
- }
- deleteSelected();
- }
- });
- });
- }
- $('#select_checkbox').on("click", function(){
- let targets = document.querySelectorAll('#file_manager_list_body .form-check-input');
- if (!targets){
- return;
- }
- dt.rows().deselect();
- let isChecked = $(this).is(':checked');
- if (isChecked){
- dt.rows({page: 'current'}).select();
- }
- KTUtil.each(targets, function (target) {
- if (target){
- target.checked = isChecked;
- }
- });
- toggleToolbars();
- });
- toggleToolbars();
- }
- var toggleToolbars = function () {
- let pageSelected = dt.rows({ selected: true, page: 'current' }).count();
- let totalSelected = dt.rows({ selected: true , search: 'applied'}).count();
- handleToogleToolbar(pageSelected, totalSelected);
- }
- return {
- init: function () {
- initLightbox();
- initDatatable();
- handleSearchDatatable();
- initToggleToolbar();
- }
- }
- }();
- function getNameFromMeta(meta) {
- return meta.split('_').slice(1).join('_');
- }
- function getTypeFromMeta(meta) {
- return meta.split('_')[0];
- }
- //{{- if not .ShareUploadBaseURL}}
- function onDirBrowserClick(dirPath) {
- KTDatatablesFoldersExplorer.init('{{.DirsURL}}?dirtree=1&path='+dirPath, dirPath);
- }
- function moveOrCopyItem(meta) {
- $('#errorMsg').addClass("d-none");
- $('#move_copy_name_container').removeClass("d-none");
- $('#move_copy_source').val(meta);
- $('#move_copy_name').val(getNameFromMeta(meta));
- $('#modal_move_or_copy').modal('show');
- KTDatatablesFoldersExplorer.init('{{.DirsURL}}?dirtree=1&path={{.CurrentDir}}', '{{.CurrentDir}}');
- }
- function getMoveOtCopyItems() {
- let items = [];
- let targetDir = $("#move_copy_folder").val();
- if (targetDir != "/") {
- targetDir = targetDir.endsWith('/') ? targetDir.slice(0, -1) : targetDir;
- }
- if (targetDir.trim() == ""){
- targetDir = "{{.CurrentDir}}";
- } else {
- targetDir = encodeURIComponent(targetDir);
- }
- if ($('#move_copy_name_container').hasClass("d-none")){
- let dt = $('#file_manager_list').DataTable();
- dt.rows({ selected: true, search: 'applied' }).every(function (rowIdx, tableLoop, rowLoop){
- let row = dt.row(rowIdx);
- let sourceName = getNameFromMeta(row.data()['meta']);
- items.push({
- targetDir: targetDir,
- sourceName: sourceName,
- targetName: sourceName
- });
- });
- } else {
- let meta = $('#move_copy_source').val();
- let sourceName = getNameFromMeta(meta);
- items.push({
- targetDir: targetDir,
- sourceName: sourceName,
- targetName: $("#move_copy_name").val()
- });
- }
- return items;
- }
- function doCopy() {
- let items = getMoveOtCopyItems();
- if (items.length == 0){
- return;
- }
- keepAlive();
- let keepAliveTimer = setInterval(keepAlive, 300000);
- let hasError = false;
- let index = 0;
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- errDivEl.addClass("d-none");
- $('#loading_message').text("");
- KTApp.showPageLoading();
- function copyItem() {
- if (index >= items.length || hasError){
- clearInterval(keepAliveTimer);
- KTApp.hidePageLoading();
- if (!hasError){
- location.reload();
- }
- return;
- }
- let item = items[index];
- let sourcePath = decodeURIComponent('{{.CurrentDir}}');
- if (!sourcePath.endsWith('/')){
- sourcePath+="/";
- }
- sourcePath+=item.sourceName;
- let targetPath = decodeURIComponent(item.targetDir);
- if (!targetPath.endsWith('/')){
- targetPath+="/";
- }
- targetPath+=item.targetName;
- if (items.length > 1){
- let msgTxt = `${sourcePath} => ${targetPath}`;
- msgTxt = `Copy ${index+1}/${items.length}: ${msgTxt}`;
- $('#loading_message').text(msgTxt);
- }
- let path = '{{.FileActionsURL}}/copy';
- path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+item.sourceName)+'&target='+item.targetDir+encodeURIComponent("/"+item.targetName);
- axios.post(path, null, {
- timeout: 180000,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 200;
- }
- }).then(function (response) {
- index++;
- copyItem();
- }).catch(function (error) {
- index++;
- hasError = true;
- let errorMessage = "Error copying item";
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- copyItem();
- });
- }
- copyItem();
- }
- function doMove() {
- let items = getMoveOtCopyItems();
- if (items.length == 0){
- return;
- }
- keepAlive();
- let keepAliveTimer = setInterval(keepAlive, 300000);
- let hasError = false;
- let index = 0;
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- errDivEl.addClass("d-none");
- $('#loading_message').text("");
- KTApp.showPageLoading();
- function moveItem() {
- if (index >= items.length || hasError){
- clearInterval(keepAliveTimer);
- KTApp.hidePageLoading();
- if (!hasError){
- location.reload();
- }
- return;
- }
- let item = items[index];
- let sourcePath = decodeURIComponent('{{.CurrentDir}}');
- if (!sourcePath.endsWith('/')){
- sourcePath+="/";
- }
- sourcePath+=item.sourceName;
- let targetPath = decodeURIComponent(item.targetDir);
- if (!targetPath.endsWith('/')){
- targetPath+="/";
- }
- targetPath+=item.targetName;
- if (items.length > 1){
- let msgTxt = `${sourcePath} => ${targetPath}`;
- msgTxt = `Move ${index+1}/${items.length}: ${msgTxt}`;
- $('#loading_message').text(msgTxt);
- }
- let path = '{{.FileActionsURL}}/move';
- path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+item.sourceName)+'&target='+item.targetDir+encodeURIComponent("/"+item.targetName);
- axios.post(path, null, {
- timeout: 180000,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 200;
- }
- }).then(function (response) {
- index++;
- moveItem();
- }).catch(function (error) {
- index++;
- hasError = true;
- let errorMessage = "Error moving item";
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- moveItem();
- });
- }
- moveItem();
- }
- function getDeleteReqAttrs(meta) {
- let path;
- let reqTimeout = 15000;
- let itemType = getTypeFromMeta(meta);
- let itemName = getNameFromMeta(meta);
- if (itemType == "1"){
- path = '{{.DirsURL}}';
- reqTimeout = 120000
- } else {
- path = '{{.FilesURL}}';
- }
- path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+itemName);
- return { path, reqTimeout}
- }
- function deleteItem(meta) {
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- errDivEl.addClass("d-none");
- let itemName = getNameFromMeta(meta);
- ModalAlert.fire({
- text: `Do you want to delete "${itemName}"? This action is irreversible`,
- icon: "warning",
- confirmButtonText: "Delete",
- cancelButtonText: 'Cancel',
- customClass: {
- confirmButton: "btn btn-danger",
- cancelButton: 'btn btn-secondary'
- }
- }).then((result) => {
- if (result.isConfirmed){
- $('#loading_message').text("");
- KTApp.showPageLoading();
- let attrs = getDeleteReqAttrs(meta);
- axios.delete(attrs.path, {
- timeout: attrs.reqTimeout,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 200;
- }
- }).then(function(response){
- location.reload();
- }).catch(function(error){
- KTApp.hidePageLoading();
- let errorMessage = `Unable to delete "${itemName}"`;
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- });
- }
- });
- }
- function shareItem(meta) {
- let filesArray = [];
- filesArray.push(getNameFromMeta(meta));
- let files = encodeURIComponent(JSON.stringify(filesArray));
- let shareURL = '{{.ShareURL}}';
- let currentDir = '{{.CurrentDir}}';
- let ts = new Date().getTime().toString();
- window.open(`${shareURL}?path=${currentDir}&files=${files}&_=${ts}`,'_blank');
- }
- function renameItem(meta) {
- $('#errorMsg').addClass("d-none");
- let oldName = getNameFromMeta(meta);
- $('#rename_old_name').val(meta);
- $('#rename_new_name').val(oldName);
- $('#rename_title').text(`Rename "${oldName}"`);
- $('#modal_rename').modal('show');
- }
- function doRename() {
- let meta = $('#rename_old_name').val();
- let oldName = getNameFromMeta(meta);
- let newName = $('#rename_new_name').val();
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- if (!newName){
- errTxtEl.text("New name is required");
- errDivEl.removeClass("d-none");
- return;
- }
- if (newName == oldName){
- errTxtEl.text("The new name must be different from the current name");
- errDivEl.removeClass("d-none");
- return;
- }
- let path = '{{.FileActionsURL}}/move';
- path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+oldName)+'&target={{.CurrentDir}}'+encodeURIComponent("/"+newName);
- axios.post(path, null, {
- timeout: 15000,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 200;
- }
- }).then(function (response) {
- location.reload();
- }).catch(function (error) {
- let errorMessage = `Unable to rename "${oldName}"`;
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- });
- }
- function showCreateNewFolder(sender) {
- if (sender == 0) {
- $('#file_manager_new_folder').removeClass("d-none");
- $('#errorMsg').addClass("d-none");
- let el = $('#file_manager_new_folder_input');
- el.val("");
- el.focus();
- return;
- }
- $('#dirsbrowser_new_folder').removeClass("d-none");
- $('#errorModalMsg').addClass("d-none");
- let el = $('#dirsbrowser_new_folder_input');
- el.val("");
- el.focus();
- }
- function hideCreateNewFolder(sender) {
- if (sender == 0){
- $('#file_manager_new_folder').addClass("d-none");
- } else {
- $('#dirsbrowser_new_folder').addClass("d-none");
- }
- }
- function createNewFolder() {
- let errDivEl = $('#errorMsg');
- let errTxtEl = $('#errorTxt');
- let dirName = replaceSlash($("#file_manager_new_folder_input").val());
- let submitButton = document.querySelector('#file_manager_add_folder');
- let cancelButton = document.querySelector('#file_manager_cancel_folder');
- errDivEl.addClass("d-none");
- if (!dirName){
- errTxtEl.text("Folder name is required");
- errDivEl.removeClass("d-none");
- return;
- }
- let path = '{{.DirsURL}}?path={{.CurrentDir}}' + encodeURIComponent("/"+dirName);
- submitButton.setAttribute('data-kt-indicator', 'on');
- submitButton.disabled = true;
- cancelButton.disabled = true;
- axios.post(path, null, {
- timeout: 15000,
- headers: {
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- validateStatus: function (status) {
- return status == 201;
- }
- }).then(function (response) {
- location.reload();
- }).catch(function (error) {
- let errorMessage = "Unable to create the new folder";
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- errTxtEl.text(errorMessage);
- errDivEl.removeClass("d-none");
- submitButton.removeAttribute('data-kt-indicator');
- submitButton.disabled = false;
- cancelButton.disabled = false;
- });
- }
- //{{- end}}
- var playerKeepAlive;
- function uploadFiles(files) {
- keepAlive();
- let keepAliveTimer = setInterval(keepAlive, 300000);
- let has_errors = false;
- let index = 0;
- let success = 0;
- $('#errorMsg').addClass("d-none");
- $('#loading_message').text("");
- KTApp.showPageLoading();
- function uploadFile() {
- if (index >= files.length || has_errors) {
- //console.log("upload done, index: "+index+" has errors: "+has_errors+" ok: "+success);
- clearInterval(keepAliveTimer);
- KTApp.hidePageLoading();
- if (!has_errors) {
- location.reload();
- }
- return;
- }
- let f = files[index];
- let uploadPath;
- //{{- if .ShareUploadBaseURL}}
- uploadPath = '{{.ShareUploadBaseURL}}' + fixedEncodeURIComponent("/"+escapeHTML(f.name));
- //{{- else}}
- uploadPath = '{{.FileURL}}?path={{.CurrentDir}}' + encodeURIComponent("/" + f.name);
- //{{- end}}
- let lastModified;
- try {
- lastModified = f.lastModified;
- } catch (e) {
- console.log("unable to get last modified time from file: " + e.message);
- lastModified = "";
- }
- let uploadTxt = f.name;
- if (files.length > 1){
- uploadTxt = `Upload ${index+1}/${files.length}: ${uploadTxt}`;
- }
- $('#loading_message').text(uploadTxt);
- axios.post(uploadPath, f, {
- headers: {
- 'X-SFTPGO-MTIME': lastModified,
- 'X-CSRF-TOKEN': '{{.CSRFToken}}'
- },
- onUploadProgress: function (progressEvent) {
- if (!progressEvent.total){
- return;
- }
- const percentage = Math.round((100 * progressEvent.loaded) / progressEvent.total);
- if (percentage > 0 && percentage < 100){
- $('#loading_message').text(`${uploadTxt} ${percentage}%`);
- }
- },
- validateStatus: function (status) {
- return status == 201;
- }
- }).then(function (response) {
- index++;
- success++;
- uploadFile();
- }).catch(function (error) {
- let errorMessage = "Error uploading files";
- if (error && error.response) {
- if (error.response.data.message) {
- errorMessage = error.response.data.message;
- }
- if (error.response.data.error) {
- errorMessage += ": " + error.response.data.error;
- }
- }
- index++;
- has_errors = true;
- $('#errorTxt').text(errorMessage);
- $('#errorMsg').removeClass("d-none");
- uploadFile();
- });
- }
- uploadFile();
- }
- function openMediaPlayer(name, url){
- $("#video_title").text(name);
- $("#video_player").attr("src", url);
- $("#video_player").get(0).load();
- $('#modal_video_player').modal('show');
- keepAlive();
- playerKeepAlive = setInterval(keepAlive, 300000);
- }
- // On document ready
- KTUtil.onDOMContentLoaded(function () {
- KTDatatablesServerSide.init();
- var dropzone = new Dropzone("#upload_files", {
- url: "{{.FilesURL}}?path={{.CurrentDir}}",
- paramName: "filenames",
- maxFiles: 250,
- maxFilesize: null,
- autoQueue: false,
- addRemoveLinks: true,
- autoProcessQueue: false,
- filesizeBase: 1000,
- init: function() {
- var dropzone = this;
- $("#upload_files_button").click(function(){
- uploadFiles(dropzone.getAcceptedFiles());
- });
- }
- });
- dropzone.on("addedfile", file => {
- file.previewElement.querySelector(".dz-progress").style.display = 'none';
- });
- $('#modal_video_player').on('hide.bs.modal', function () {
- $("#video_player").get(0).pause();
- if (playerKeepAlive != null) {
- clearInterval(playerKeepAlive);
- playerKeepAlive = null;
- }
- });
- //{{- if not .ShareUploadBaseURL}}
- $('#modal_rename').on('shown.bs.modal', function () {
- let newNameEl = $('#rename_new_name');
- newNameEl.focus();
- newNameEl.select();
- });
- //{{- end}}
- // onclick handlers
- var createDirBtn = $('#id_create_dir_button');
- if (createDirBtn){
- createDirBtn.on("click", function (){
- showCreateNewFolder(0);
- });
- }
- var dirBrowserCreateDir = $('#id_dir_browser_create_dir');
- if (dirBrowserCreateDir){
- dirBrowserCreateDir.on("click", function(){
- showCreateNewFolder(1);
- });
- }
- var fileManagerAddFolder = $('#file_manager_add_folder');
- if (fileManagerAddFolder){
- fileManagerAddFolder.on("click", function() {
- createNewFolder();
- });
- }
- var fileManagerCancelCreateFolder = $('#file_manager_cancel_folder');
- if (fileManagerCancelCreateFolder){
- fileManagerCancelCreateFolder.on("click", function(){
- hideCreateNewFolder(0);
- })
- }
- var dirBrowserCancelCreateFolder = $('#dirsbrowser_cancel_folder');
- if (dirBrowserCancelCreateFolder){
- dirBrowserCancelCreateFolder.on("click", function(){
- hideCreateNewFolder(1);
- });
- }
- var doRenameBtn = $('#id_do_rename_button');
- if (doRenameBtn){
- doRenameBtn.on("click", function() {
- doRename();
- });
- }
- var doCopyBtn = $('#id_copy_button');
- if (doCopyBtn){
- doCopyBtn.on("click", function(){
- doCopy();
- });
- }
- var doMoveBtn = $('#id_move_button');
- if (doMoveBtn){
- doMoveBtn.on("click", function(){
- doMove();
- });
- }
- var dismissErrorModalBtn = $('#id_dismiss_error_modal_msg');
- if (dismissErrorModalBtn){
- dismissErrorModalBtn.on("click",function(){
- $('#errorModalMsg').addClass("d-none");
- });
- }
- });
- </script>
- {{- end}}
- {{- define "additionalnavitems"}}
- {{- if .QuotaUsage.HasQuotaInfo}}
- <div class="d-flex align-items-center ms-2 ms-lg-3">
- <div class="btn btn-icon btn-active-light-primary position-relative w-35px h-35px w-md-40px h-md-40px" data-kt-menu-trigger="{default:'click', lg: 'hover'}" data-kt-menu-attach="parent" data-kt-menu-placement="bottom-end">
- <i class="ki-duotone {{if .QuotaUsage.IsQuotaLow}}ki-information-5 text-warning{{else}}ki-information-2{{end}} fs-2">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- </i>
- </div>
- <div class="menu menu-sub menu-sub-dropdown menu-column w-350px" data-kt-menu="true">
- <div class="card">
- <div class="card-header">
- <h3 class="card-title"><span class="text-gray-700 fw-semibold fs-6">Quota usage</span></h3>
- </div>
- <div class="card-body p-0">
- {{- if .QuotaUsage.HasDiskQuota}}
- {{- $size := .QuotaUsage.GetQuotaSize}}
- {{- $files := .QuotaUsage.GetQuotaFiles}}
- <div class="d-flex align-items-center bg-hover-lighten py-3 px-9">
- <div class="symbol symbol-40px symbol-circle me-5">
- <span class="symbol-label {{ if .QuotaUsage.IsDiskQuotaLow }}bg-light-warning{{end}}">
- <i class="ki-duotone ki-external-drive {{ if .QuotaUsage.IsDiskQuotaLow }}text-warning{{end}} fs-1">
- <span class="path1"></span>
- <span class="path2"></span>
- <span class="path3"></span>
- <span class="path4"></span>
- <span class="path5"></span>
- </i>
- </span>
- </div>
- <div class="mb-1 pe-3 flex-grow-1">
- <span class="fs-6 text-gray-900 fw-semibold">Disk quota</span>
- {{- if $size}}
- {{- $percentage := .QuotaUsage.GetQuotaSizePercentage}}
- <div class="{{if .QuotaUsage.IsQuotaSizeLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">Size: {{$size}}{{if gt $percentage 0}} ({{$percentage}}%){{end}}</div>
- {{- end}}
- {{- if $files}}
- {{- $percentage := .QuotaUsage.GetQuotaFilesPercentage}}
- <div class="{{if .QuotaUsage.IsQuotaFilesLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">Files: {{$files}}{{if gt $percentage 0}} ({{$percentage}}%){{end}}</div>
- {{- end}}
- </div>
- </div>
- {{- end}}
- {{- if .QuotaUsage.HasTranferQuota}}
- {{- $total := .QuotaUsage.GetTotalTransferQuota}}
- {{- $upload := .QuotaUsage.GetUploadTransferQuota}}
- {{- $download := .QuotaUsage.GetDownloadTransferQuota}}
- <div class="d-flex align-items-center bg-hover-lighten py-3 px-9">
- <div class="symbol symbol-40px symbol-circle me-5">
- <span class="symbol-label {{ if .QuotaUsage.IsTransferQuotaLow }}bg-light-warning{{end}}">
- <i class="ki-duotone ki-arrow-right-left {{ if .QuotaUsage.IsTransferQuotaLow }}text-warning{{end}} fs-1">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- </span>
- </div>
- <div class="mb-1 pe-3 flex-grow-1">
- <span class="fs-6 text-gray-900 fw-semibold">Transfer quota</span>
- {{- if $total}}
- {{$percentage := .QuotaUsage.GetTotalTransferQuotaPercentage}}
- <div class="{{if .QuotaUsage.IsTotalTransferQuotaLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">Total: {{$total}}{{if gt $percentage 0}} ({{$percentage}}%){{end}}</div>
- {{- end}}
- {{- if $download}}
- {{$percentage := .QuotaUsage.GetDownloadTransferQuotaPercentage}}
- <div class="{{if .QuotaUsage.IsDownloadTransferQuotaLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">Download: {{$download}}{{if gt $percentage 0}} ({{$percentage}}%){{end}}</div>
- {{- end}}
- {{- if $upload}}
- {{$percentage := .QuotaUsage.GetUploadTransferQuotaPercentage}}
- <div class="{{if .QuotaUsage.IsUploadTransferQuotaLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">Upload: {{$upload}}{{if gt $percentage 0}} ({{$percentage}}%){{end}}</div>
- {{- end}}
- </div>
- </div>
- {{- end}}
- </div>
- </div>
- </div>
- </div>
- {{- end}}
- {{- end}}
- {{- define "modals"}}
- <div class="modal fade" tabindex="-1" id="modal_upload">
- <div class="modal-dialog modal-dialog-centered mw-600px">
- <div class="modal-content">
- <div class="modal-header border-0">
- <h3 class="modal-title">Upload files</h3>
- <div class="btn btn-icon btn-sm btn-active-color-primary" data-bs-dismiss="modal" aria-label="Close">
- <i class="ki-duotone ki-cross fs-1"><span class="path1"></span><span class="path2"></span></i>
- </div>
- </div>
- <div class="modal-body">
- <form id="upload_files_form" action="{{.FilesURL}}?path={{.CurrentDir}}" method="POST" enctype="multipart/form-data">
- <div class="fv-row">
- <div class="dropzone" id="upload_files">
- <div class="dz-message needsclick align-items-center">
- <i class="ki-duotone ki-file-up fs-3x text-primary"><span class="path1"></span><span class="path2"></span></i>
- <div class="ms-4">
- <h3 class="fs-5 fw-bold text-gray-900 mb-1">Drop files here or click to upload.</h3>
- <!-- <span class="fs-7 fw-semibold text-gray-500">Upload up to 30 files</span> -->
- </div>
- </div>
- </div>
- </div>
- </form>
- </div>
- <div class="modal-footer border-0">
- <button type="button" class="btn btn-light me-5" data-bs-dismiss="modal">Cancel</button>
- <button type="button" id="upload_files_button" class="btn btn-primary" data-bs-dismiss="modal">Submit</button>
- </div>
- </div>
- </div>
- </div>
- <div class="modal fade" tabindex="-1" id="modal_video_player" data-bs-backdrop="static" data-bs-keyboard="false">
- <div class="modal-dialog modal-dialog-centered modal-lg">
- <div class="modal-content">
- <div class="modal-header border-0">
- <h5 class="modal-title">
- <span id="video_title"></span>
- </h5>
- <div class="btn btn-icon btn-sm btn-active-color-primary" data-bs-dismiss="modal" aria-label="Close">
- <i class="ki-duotone ki-cross fs-1"><span class="path1"></span><span class="path2"></span></i>
- </div>
- </div>
- <div class="modal-body">
- <video id="video_player" width="100%" height="auto" controls preload="metadata">
- Your browser does not support HTML5 video.
- </video>
- </div>
- </div>
- </div>
- </div>
- {{- if not .ShareUploadBaseURL}}
- <div class="modal fade" tabindex="-1" id="modal_rename">
- <div class="modal-dialog modal-dialog-centered">
- <div class="modal-content">
- <div class="modal-header border-0">
- <h5 class="modal-title">
- <span id="rename_title"></span>
- </h5>
- <div class="btn btn-icon btn-sm btn-active-color-primary" data-bs-dismiss="modal" aria-label="Close">
- <i class="ki-duotone ki-cross fs-1"><span class="path1"></span><span class="path2"></span></i>
- </div>
- </div>
- <div class="modal-body">
- <input id="rename_old_name" type="text" class="d-none"/>
- <div class="mb-10">
- <label for="rename_new_name" class="form-label">New name</label>
- <input id="rename_new_name" type="text" class="form-control"/>
- </div>
- </div>
- <div class="modal-footer border-0">
- <button type="button" class="btn btn-secondary me-5" data-bs-dismiss="modal">Cancel</button>
- <button id="id_do_rename_button" type="button" class="btn btn-primary" data-bs-dismiss="modal">Submit</button>
- </div>
- </div>
- </div>
- </div>
- <div class="modal fade" tabindex="-1" id="modal_move_or_copy">
- <div class="modal-dialog modal-dialog-centered modal-lg">
- <div class="modal-content">
- <div class="modal-header border-0">
- <h3 class="modal-title">
- Choose target folder
- </h3>
- <div class="btn btn-icon btn-sm btn-active-color-primary" data-bs-dismiss="modal" aria-label="Close">
- <i class="ki-duotone ki-cross fs-1"><span class="path1"></span><span class="path2"></span></i>
- </div>
- </div>
- <div class="modal-body">
- <div id="errorModalMsg" class="d-none alert alert-dismissible bg-light-warning d-flex align-items-center p-5 mb-10">
- <i class="ki-duotone ki-information-5 fs-3x text-warning me-5"><span class="path1"></span><span class="path2"></span><span class="path3"></span></i>
- <div class="text-gray-700 fw-bold fs-5 d-flex flex-column pe-0 pe-sm-10">
- <span id="errorModalTxt"></span>
- </div>
- <button id="id_dismiss_error_modal_msg" type="button" class="position-absolute position-sm-relative m-2 m-sm-0 top-0 end-0 btn btn-icon btn-sm btn-active-light-primary ms-sm-auto">
- <i class="ki-duotone ki-cross fs-2x text-primary"><span class="path1"></span><span class="path2"></span></i>
- </button>
- </div>
- <div class="row">
- <div class="col-md-9 align-items-center d-flex flex-stack">
- <div class="badge badge-lg badge-light-primary">
- <div id="dirs_browser_nav" class="d-flex align-items-center flex-wrap">
- </div>
- </div>
- </div>
- <div class="col-md-3 align-items-center d-flex justify-content-end">
- <button id="id_dir_browser_create_dir" type="button" class="btn btn-flex btn-primary">
- <i class="ki-duotone ki-add-folder fs-2">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- Add
- </button>
- </div>
- </div>
- <div id="dirsbrowser_new_folder" class="d-flex align-items-center py-7 d-none">
- <span>
- <i class="ki-duotone ki-folder fs-2x text-primary me-4">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- </span>
- <input id="dirsbrowser_new_folder_input" type="text" name="new_folder_name" placeholder="Enter the new folder name" class="form-control mw-250px me-3" />
- <button class="btn btn-icon btn-light-primary me-3" id="dirsbrowser_add_folder">
- <span class="indicator-label">
- <i class="ki-duotone ki-check fs-1"></i>
- </span>
- <span class="indicator-progress">
- <span class="spinner-border spinner-border-sm align-middle"></span>
- </span>
- </button>
- <button class="btn btn-icon btn-light-danger" id="dirsbrowser_cancel_folder">
- <i class="ki-duotone ki-cross fs-1">
- <span class="path1"></span>
- <span class="path2"></span>
- </i>
- </button>
- </div>
- <table id="dirsbrowser_list" class="table align-middle table-row-dashed fs-6 gy-5">
- <thead>
- <tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
- <th></th>
- <th class="min-w-250px">Name</th>
- </tr>
- </thead>
- <tbody id="dirsbrowser_list_body" class="text-gray-600 fw-semibold">
- </tbody>
- </table>
- <div class="form-floating d-none">
- <input type="text" class="form-control form-control-solid" id="move_copy_source"/>
- <label for="move_copy_source">Source name</label>
- </div>
- <div class="form-floating mb-5 mt-7">
- <input type="text" class="form-control form-control-solid" id="move_copy_folder"/>
- <label for="move_copy_folder">Target folder</label>
- </div>
- <div class="form-floating" id="move_copy_name_container">
- <input type="text" class="form-control form-control-solid" id="move_copy_name"/>
- <label for="move_copy_name">Destination name</label>
- </div>
- </div>
- <div class="modal-footer border-0">
- {{- if .CanAddFiles }}
- <button id="id_copy_button" type="button" class="btn btn-light-primary me-5" data-bs-dismiss="modal">Copy</button>
- {{- end}}
- {{- if .CanRename }}
- <button id="id_move_button" type="button" class="btn btn-primary" data-bs-dismiss="modal">Move</button>
- {{- end}}
- </div>
- </div>
- </div>
- </div>
- {{- end}}
- {{- end}}
|