<!--
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 (support@sftpgo.com).
-->
{{template "base" .}}

{{- define "page_body"}}
{{- template "errmsg" .Error}}

{{- $move_copy_msg := ""}}
{{- if and .CanRename .CanCopy}}
{{- $move_copy_msg = "fs.move_copy"}}
{{- else}}
{{- if .CanRename}}
{{- $move_copy_msg = "fs.move.msg"}}
{{- else}}
{{- if .CanCopy}}
{{- $move_copy_msg = "fs.copy.msg"}}
{{- end}}
{{- end}}
{{- end}}

<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-solid ki-magnifier fs-1 position-absolute ms-6"></i>
                <input name="search" data-i18n="[placeholder]general.search" type="text" data-kt-filemanager-table-filter="search" class="form-control rounded-1 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>
                    <span data-i18n="fs.new_folder">New Folder</span>
                </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>
                    <span data-i18n="fs.upload.text">Upload Files</span>
                </button>
                {{- end}}
            </div>
        </div>
    </div>
    <div class="card-body">
        <div class="d-flex flex-stack">
            <div class="badge badge-lg badge-light-primary" data-kt-filemanager-table-nav-bar="base">
                <div class="d-flex align-items-center flex-wrap">
                    <i class="ki-duotone ki-home fs-1 text-primary me-3"></i>
                    <a data-i18n="fs.home" 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 class="d-flex 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 data-i18n="fs.select_across_pages" 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">
                        <span data-i18n="general.actions">Actions</span>
                        <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 data-i18n="fs.download" 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 data-i18n="{{$move_copy_msg}}" 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 data-i18n="fs.share" 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 data-i18n="general.delete" 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 class="new_folder_divider py-2 d-none">
            <hr>
        </div>
        <div id="file_manager_new_folder" class="d-flex align-items-center 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 data-i18n="[placeholder]fs.create_folder_msg" 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-solid ki-cross fs-1"></i>
            </button>
        </div>
        <div class="new_folder_divider py-2 d-none">
            <hr>
        </div>
        <div id="upload_files_empty_container" class="d-none mt-10">
            <form id="upload_files_empty_form" action="{{.FilesURL}}?path={{.CurrentDir}}" method="POST" enctype="multipart/form-data">
                <div class="fv-row">
                    <div class="dropzone mh-350px overflow-auto visibility-auto" id="upload_files_empty">
                        <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 data-i18n="fs.upload.message_empty" class="fs-5 fw-bold text-gray-900 mb-1"></h3>
                                <!-- <span class="fs-7 fw-semibold text-gray-500">Upload up to 30 files</span> -->
                            </div>
                        </div>
                    </div>
                </div>
            </form>
            <div class="d-flex justify-content-end mt-5">
                <button data-i18n="general.submit" type="button" id="upload_files_empty_button" class="btn btn-primary">Submit</button>
            </div>
        </div>
        <div id="loader" class="align-items-center text-center my-10">
            <span class="spinner-border w-15px h-15px text-muted align-middle me-2"></span>
            <span data-i18n="general.loading" class="text-gray-700">Loading...</span>
        </div>
        <div id="file_manager_list_container" class="d-none">
            <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 text-gray-500">
                        <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 data-i18n="general.name" class="min-w-250px">Name</th>
                        <th data-i18n="general.size" class="min-w-10px">Size</th>
                        <th data-i18n="general.last_modified" 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>
</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 {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/assets/plugins/custom/datatables/datatables.bundle.js"></script>
<script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/vendor/glightbox/glightbox.min.js"></script>
<script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/vendor/pdfobject/pdfobject.min.js"></script>
<script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
    //{{- $move_copy_msg := ""}}
    //{{- if and .CanRename .CanCopy}}
    //{{- $move_copy_msg = "fs.move_copy"}}
    //{{- else}}
    //{{- if .CanRename}}
    //{{- $move_copy_msg = "fs.move.msg"}}
    //{{- else}}
    //{{- if .CanCopy}}
    //{{- $move_copy_msg = "fs.copy.msg"}}
    //{{- end}}
    //{{- end}}
    //{{- end}}

    const dzPreviewTemplate = `<div class="d-flex align-items-center mb-2">
                                 <span class="bullet bullet-dot bg-primary me-2"></span>
                                 <div class="text-break text-wrap text-left"><span class="fs-5 fw-semibold" data-dz-name></span>&nbsp;(<span class="fs-5 fw-semibold" data-custom-size></span>)</div>
                               </div>
                               <div class="dz-error-message d-none" data-dz-errormessage></div>
                               <div class="dz-progress d-none"><span class="dz-upload" data-dz-uploadprogress></span></div>
                              `;

    //{{- 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}}
    }

    var taskStatusWaiter = function () {
        var promiseResolve;

        function getTaskStatus(taskID, numErrors) {
            axios.get('{{.TasksURL}}'+"/"+encodeURIComponent(taskID),{
                timeout: 15000,
                headers: {
                    'X-CSRF-TOKEN': '{{.CSRFToken}}'
                },
                validateStatus: function (status) {
                    return status == 200;
                }
            }).then(function(response){
                let status = response.data.status;
                if (status == 0){
                    setTimeout(function() {
                        getTaskStatus(taskID, numErrors);
                    }, 2500);
                } else {
                    promiseResolve({
                        status: status
                    });
                }
            }).catch(function(error){
                numErrors++;
                if (numErrors >= 3){
                    promiseResolve({
                        status: 0
                    });
                    return;
                }
                if (error && error.response && error.response.status == 404){
                    promiseResolve({
                        status: 404
                    });
                    return;
                }
                setTimeout(function() {
                    getTaskStatus(taskID, numErrors);
                }, 2500);
            });
        }

        return {
            wait: function(params){
                setTimeout(function() {
                    getTaskStatus(params.taskID, 0);
                }, params.delay);

                return new Promise(function(resolve, reject) {
                    promiseResolve = resolve;
                });
            }
        }
    }();

    //{{- 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) {
                        $(".dt-processing").hide();
                        let txt = "";
                        if ($xhr) {
                            let json = $xhr.responseJSON;
                            if (json) {
                                if (json.message) {
                                    txt = json.message;
                                }
                            }
                        }
                        if (!txt){
                            txt = "fs.dir_list.err_generic";
                        }
                        setI18NData($('#errorModalTxt'), 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: {
                    info: $.t('datatable.info'),
                    infoEmpty: $.t('datatable.info_empty'),
                    infoFiltered: $.t('datatable.info_filtered'),
                    loadingRecords: "",
                    processing: $.t('datatable.processing'),
                    zeroRecords: "",
                    emptyTable: $.t('fs.no_more_subfolders')
                },
                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 = $.t('fs.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 = $("#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){
                    setI18NData(errTxtEl, "fs.folder_name_required");
                    errDivEl.removeClass("d-none");
                    return;
                }
                if (dirName.includes("/")){
                    setI18NData(errTxtEl, "fs.invalid_name");
                    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;
                    $('.dir_browser_folder_divider').addClass("d-none");
                    $('#dirsbrowser_new_folder').addClass("d-none");
                }).catch(function (error) {
                    let errorMessage = "";
                    if (error && error.response) {
                        switch (error.response.status) {
                            case 403:
                                errorMessage = "fs.create_dir.err_403";
                                break;
                            case 429:
                                errorMessage = "fs.create_dir.err_429";
                                break;
                        }
                    }
                    if (!errorMessage){
                        errorMessage = "fs.create_dir.err_generic";
                    }
                    setI18NData(errTxtEl, 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 => {
                let el = $(d);
                el.off("click");
                el.on("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 dt;
        var lightbox;


        // Private functions
        var initDatatable = function () {
            dt = $("#file_manager_list").DataTable({
                ajax: {
                    url: "{{.DirsURL}}?path={{.CurrentDir}}",
                    dataSrc: "",
                    error: function ($xhr, textStatus, errorThrown) {
                        $(".dt-processing").hide();
                        $('#loader').addClass("d-none");
                        let txt = "";
                        if ($xhr) {
                            let json = $xhr.responseJSON;
                            if (json) {
                                if (json.message){
                                    txt = json.message;
                                }
                            }
                        }
                        if (!txt){
                            txt = "fs.dir_list.err_generic";
                        }
                        setI18NData($('#errorTxt'), 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",
                        render: function (data, type, row) {
                            if (type === 'display') {
                                if (data){
                                    return $.t('general.datetime', {
                                        val: new Date(data),
                                        formatParams: {
                                            val: { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' },
                                        }
                                    });
                                }
                                return ""
                            }
                            return data;
                        }
                    },
                    {
                        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, '&quot;');
                                            previewDiv = `<div class="ms-2" data-kt-filemanger-table="view_item">
												    <a href="${row['url']}" data-gallery="gallery" data-glightbox="description: &lt;span class=&quot;fs-5 fw-bold&quot;&gt;${desc}&lt;/span&gt;" class="btn btn-sm btn-icon btn-light btn-active-light-primary glightbox">
													    <i class="ki-duotone ki-eye fs-6 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-6 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-6 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-6 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-6 w-150px py-4" data-kt-menu="true">
													{{- if .CanRename}}
                                                    <div class="menu-item px-3">
														<a data-i18n="general.rename" href="#" class="menu-link px-3" data-kt-filemanager-table-action="rename">Rename</a>
													</div>
                                                    {{- end}}
                                                    {{- if or .CanRename .CanCopy}}
													<div class="menu-item px-3">
														<a data-i18n="{{$move_copy_msg}}" 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 data-i18n="fs.share" 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 data-i18n="general.delete" 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: {
                    info: $.t('datatable.info'),
                    infoEmpty: $.t('datatable.info_empty'),
                    infoFiltered: $.t('datatable.info_filtered'),
                    loadingRecords: "",
                    processing: $.t('datatable.processing'),
                    zeroRecords: "",
                    emptyTable: $.t('fs.no_files_folders')
                },
                orderFixed: [1, 'asc'],
                order: [2, 'asc'],
                initComplete: function(settings, json) {
                    $('#loader').addClass("d-none");
                    $('#file_manager_list_container').removeClass("d-none");
                    let api = $.fn.dataTable.Api(settings);
                    api.columns.adjust().draw("page");
                    drawAction();
                }
            });

            dt.on('draw', drawAction);

            function drawAction() {
                //{{- if .CanAddFiles}}
                if (dt.rows().count() === 0) {
                    $('#file_manager_list_container').addClass("d-none");
                    $('#upload_files_empty_container').removeClass("d-none");
                    return;
                }
                $('#upload_files_empty_container').addClass("d-none");
                $('#file_manager_list_container').removeClass("d-none");
                //{{- end}}
                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();
                $('#file_manager_list_body').localize();
            }

            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 navBar = document.querySelector('[data-kt-filemanager-table-nav-bar="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 =  $.t('general.selected_items', { count: totalSelected});
                }
                if (navBar){
                    navBar.classList.add('d-none');
                }
                if (toolbarSelected){
                    toolbarSelected.classList.remove('d-none');
                }
            } else {
                $('#select_checkbox').prop("checked", false);
                selectAllCheck.checked = false;
                if (navBar) {
                    navBar.classList.remove('d-none');
                }
                if (toolbarSelected) {
                    toolbarSelected.classList.add('d-none');
                }
            }
        }

        function handleRowActions() {
            const renameButtons = document.querySelectorAll('[data-kt-filemanager-table-action="rename"]');

            renameButtons.forEach(d => {
                let el = $(d);
                el.off("click");
                el.on("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 => {
                let el = $(d);
                el.off("click");
                el.on("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 => {
                let el = $(d);
                el.off("click");
                el.on("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 => {
                let el = $(d);
                el.off("click");
                el.on("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 => {
                let el = $(d);
                el.off("click");
                el.on("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.off("keyup");
            filterSearch.on('keyup', function (e) {
                dt.rows().deselect();
                dt.search(e.target.value).draw();
            });
        }

        var initToggleToolbar = function () {
            const selectAllCheck = document.querySelector('[data-kt-filemanager-table-select="select_all_pages"]');
            if (selectAllCheck){
                let el = $(selectAllCheck);
                el.off("change");
                el.on('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){
                let el = $(downloadButton);
                el.off("click");
                el.on('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){
                let el = $(moveOrCopyButton);
                el.off("click");
                el.on('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){
                let el = $(shareButton);
                el.off("click");
                el.on('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) {

                function getMultiDeleteErrorMessage(status, deleted) {
                    let errorMessage;
                    switch (status) {
                        case 403:
                            if (deleted > 0){
                                errorMessage = "fs.delete_multi.err_403_partial";
                            } else {
                                errorMessage = "fs.delete_multi.err_403";
                            }
                            break;
                        case 429:
                        if (deleted > 0){
                                errorMessage = "fs.delete_multi.err_429_partial";
                            } else {
                                errorMessage = "fs.delete_multi.err_429";
                            }
                            break;
                    }
                    if (!errorMessage){
                        if (deleted > 0){
                            errorMessage = "fs.delete_multi.err_generic_partial";
                        } else {
                            errorMessage = "fs.delete_multi.err_generic";
                        }
                    }
                    return errorMessage;
                }

                let el = $(deleteButton);
                el.off("click");
                el.on('click', function(e){
                    ModalAlert.fire({
                        text: $.t('general.delete_multi_confirm'),
                        icon: "warning",
                        confirmButtonText: $.t('general.delete_confirm_btn'),
                        cancelButtonText: $.t('general.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;
                            }
                            $('#loading_message').text("");
                            KTApp.showPageLoading();

                            function deleteSelected() {
                                if (index >= selectedRowsIdx.length || hasError){
                                    KTApp.hidePageLoading();
                                    if (!hasError){
                                        location.reload();
                                    }
                                    return;
                                }
                                let meta = dt.row(selectedRowsIdx[index]).data()['meta'];
                                let itemName = getNameFromMeta(meta);
                                let isDir = (getTypeFromMeta(meta) == "1");
                                let path;
                                if (isDir){
                                    path = '{{.DirsURL}}';
                                } else {
                                    path = '{{.FilesURL}}';
                                }
                                path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+itemName);

                                let deleteTxt = "";
                                if (selectedRowsIdx.length > 1){
                                    deleteTxt = $.t('fs.deleting', {
                                        idx : index + 1,
                                        total: selectedRowsIdx.length,
                                        name: itemName
                                    });
                                }
                                $('#loading_message').text(deleteTxt);
                                axios.delete(path,{
                                    timeout: 15000,
                                    headers: {
                                        'X-CSRF-TOKEN': '{{.CSRFToken}}'
                                    },
                                    validateStatus: function (status) {
                                        if (isDir){
                                            return status == 202;
                                        }
                                        return status == 200;
                                    }
                                }).then(function(response){
                                    if (isDir){
                                        taskStatusWaiter.wait({
                                            taskID: response.data.message,
                                            delay: 500
                                        }).then((result) => {
                                            index++;
                                            if (result.status == 200){
                                                deleted++;
                                            } else {
                                                hasError = true;
                                                let errorMessage = getMultiDeleteErrorMessage(result.status, deleted);
                                                setI18NData(errTxtEl, errorMessage);
                                                errDivEl.removeClass("d-none");
                                            }
                                            deleteSelected();
                                        });
                                    } else {
                                        index++;
                                        deleted++;
                                        deleteSelected();
                                    }
                                }).catch(function(error){
                                    index++;
                                    hasError = true;
                                    let status = 0;
                                    if (error && error.response) {
                                        status = error.response.status;
                                    }
                                    let errorMessage = getMultiDeleteErrorMessage(status, deleted);
                                    setI18NData(errTxtEl, 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 getMoveOrCopyItems() {
        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")){
            // bulk action
            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 checkMoveCopyItems(items) {
        let hasSlash = items.some(item => item.targetName.includes("/"));
        if (hasSlash){
            return [];
        }
        return items;
    }

    function doCopy() {
        $('#errorMsg').addClass("d-none");
        let items = getMoveOrCopyItems();
        if (items.length == 0){
            return;
        }
        items = checkMoveCopyItems(items)
        if (items.length == 0){
            ModalAlert.fire({
                text: $.t('fs.invalid_name'),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            return;
        }

        function showCopyError(status) {
            KTApp.hidePageLoading();
            let errorMessage = "";
            switch (status) {
                case 403:
                    errorMessage = "fs.copy.err_403";
                    break;
                case 429:
                    errorMessage = "fs.copy.err_429";
                    break;
                default:
                    errorMessage = "fs.copy.err_generic";
            }
            ModalAlert.fire({
                text: $.t(errorMessage),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
        }

        let hasError = false;
        let index = 0;

        $('#loading_message').text("");
        KTApp.showPageLoading();

        function copyItem() {
            if (index >= items.length || hasError){
                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) {
                msgTxt = $.t('fs.copying', {
                    idx: index + 1,
                    total: items.length,
                    name: `${sourcePath} => ${targetPath}`
                });
                $('#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: 15000,
                headers: {
                    'X-CSRF-TOKEN': '{{.CSRFToken}}'
                },
                validateStatus: function (status) {
                    return status == 202;
                }
            }).then(function (response) {
                taskStatusWaiter.wait({
                    taskID: response.data.message,
                    delay: 500
                }).then((result) => {
                    index++;
                    if (result.status != 200){
                        hasError = true;
                        showCopyError(result.status);
                    }
                    copyItem();
                });
            }).catch(function (error) {
                index++;
                hasError = true;
                let status = 0;
                if (error && error.response) {
                    status = error.response.status;
                }
                showCopyError(status);
                copyItem();
            });
        }

        let filesArray = [];
        for (let i = 0; i < items.length; i++){
            filesArray.push(items[i].targetName);
        }

        CheckExist.fire({
            operation: "copy",
            files: filesArray,
            path: items[0].targetDir
        }).then((result)=>{
            if (result.error) {
                hasError = true;
                ModalAlert.fire({
                    text: $.t("fs.copy.err_generic"),
                    icon: "warning",
                    confirmButtonText: $.t('general.ok'),
                    customClass: {
                        confirmButton: "btn btn-primary"
                    }
                });
            } else if (result.data.length > 0){
                hasError = true;
                ModalAlert.fire({
                    text: $.t("fs.copy.err_exists"),
                    icon: "warning",
                    confirmButtonText: $.t('general.ok'),
                    customClass: {
                        confirmButton: "btn btn-primary"
                    }
                });
            }
            copyItem();
        });
    }

    function doMove() {
        $('#errorMsg').addClass("d-none");
        let items = getMoveOrCopyItems();
        if (items.length == 0){
            return;
        }
        items = checkMoveCopyItems(items)
        if (items.length == 0){
            ModalAlert.fire({
                text: $.t("fs.invalid_name"),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            return;
        }

        function showMoveError(status) {
            KTApp.hidePageLoading();
            let errorMessage = "";
            switch (status) {
                case 400:
                    errorMessage = "fs.move.err_unsupported";
                    break;
                case 403:
                    errorMessage = "fs.move.err_403";
                    break;
                case 429:
                    errorMessage = "fs.move.err_429";
                    break;
                default:
                    errorMessage = "fs.move.err_generic";
            }
            ModalAlert.fire({
                text: $.t(errorMessage),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
        }

        let hasError = false;
        let index = 0;

        $('#loading_message').text("");
        KTApp.showPageLoading();

        function moveItem() {
            if (index >= items.length || hasError){
                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) {
                msgTxt = $.t('fs.moving', {
                    idx: index + 1,
                    total: items.length,
                    name: `${sourcePath} => ${targetPath}`
                });
                $('#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: 15000,
                headers: {
                    'X-CSRF-TOKEN': '{{.CSRFToken}}'
                },
                validateStatus: function (status) {
                    return status == 202;
                }
            }).then(function (response) {
                taskStatusWaiter.wait({
                    taskID: response.data.message,
                    delay: 500
                }).then((result) => {
                    index++;
                    if (result.status != 200){
                        hasError = true;
                        showMoveError(result.status);
                    }
                    moveItem();
                });
            }).catch(function (error) {
                index++;
                hasError = true;
                let status = 0;
                if (error && error.response) {
                    status = error.response.status;
                }
                showMoveError(status);
                moveItem();
            });
        }

        let filesArray = [];
        for (let i = 0; i < items.length; i++){
            filesArray.push(items[i].targetName);
        }

        CheckExist.fire({
            operation: "move",
            files: filesArray,
            path: items[0].targetDir
        }).then((result)=>{
            if (result.error) {
                hasError = true;
                ModalAlert.fire({
                text: $.t("fs.move.err_generic"),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            } else if (result.data.length > 0){
                hasError = true;
                ModalAlert.fire({
                text: $.t("fs.move.err_exists"),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            }
            moveItem();
        });
    }

    function showDeleteItemError(status, itemName) {
        KTApp.hidePageLoading();
        let errorMessage;
        switch (status) {
            case 403:
                errorMessage = "fs.delete.err_403";
                break;
            case 429:
                errorMessage = "fs.delete.err_429";
                break;
            default:
                errorMessage = "fs.delete.err_generic";
        }
        ModalAlert.fire({
            text: $.t(errorMessage, {name: itemName}),
            icon: "warning",
            confirmButtonText: $.t('general.ok'),
            customClass: {
                confirmButton: "btn btn-primary"
            }
        });
    }

    function deleteItem(meta) {
        $('#errorMsg').addClass("d-none");
        let itemName = getNameFromMeta(meta);

        ModalAlert.fire({
            text: $.t('general.delete_confirm', {name: itemName}),
            icon: "warning",
            confirmButtonText: $.t('general.delete_confirm_btn'),
            cancelButtonText: $.t('general.cancel'),
            customClass: {
                confirmButton: "btn btn-danger",
                cancelButton: 'btn btn-secondary'
            }
        }).then((result) => {
            if (result.isConfirmed){
                $('#loading_message').text("");
                KTApp.showPageLoading();
                let isDir = (getTypeFromMeta(meta) == "1");
                let path;
                if (isDir){
                    path = '{{.DirsURL}}';
                } else {
                    path = '{{.FilesURL}}';
                }
                path+='?path={{.CurrentDir}}'+encodeURIComponent("/"+itemName);

                axios.delete(path, {
                    timeout: 15000,
                    headers: {
                        'X-CSRF-TOKEN': '{{.CSRFToken}}'
                    },
                    validateStatus: function (status) {
                        if (isDir){
                            return status == 202;
                        }
                        return status == 200;
                    }
                }).then(function(response){
                    if (isDir){
                        taskStatusWaiter.wait({
                            taskID: response.data.message,
                            delay: 500
                        }).then((result) => {
                            if (result.status == 200){
                                location.reload();
                            } else {
                                showDeleteItemError(result.status, itemName);
                            }
                        });
                    } else {
                        location.reload();
                    }
                }).catch(function(error){
                    let status = 0;
                    if (error && error.response) {
                        status = error.response.status;
                    }
                    showDeleteItemError(status, itemName);
                });
            }
        });
    }

    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($.t('fs.rename.title', { name: oldName}));
        $('#modal_rename').modal('show');
    }

    function showRenameItemError(status, oldName) {
        KTApp.hidePageLoading();
        let errorMessage;
        switch (status) {
            case 400:
                errorMessage = "fs.rename.err_unsupported";
                break;
            case 403:
                errorMessage = "fs.rename.err_403";
                break;
            case 429:
                errorMessage = "fs.rename.err_429";
                break;
            default:
                errorMessage = "fs.rename.err_generic";
        }

        ModalAlert.fire({
            text: $.t(errorMessage, {name: oldName}),
            icon: "warning",
            confirmButtonText: $.t('general.ok'),
            customClass: {
                confirmButton: "btn btn-primary"
            }
        });
    }

    function doRename() {
        let meta = $('#rename_old_name').val();
        let oldName = getNameFromMeta(meta);
        let newName = $('#rename_new_name').val();
        if (!newName){
            ModalAlert.fire({
                text: $.t('general.name_required'),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            return;
        }
        if (newName == oldName){
            ModalAlert.fire({
                text: $.t('general.name_different'),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            return;
        }
        if (newName.includes("/")){
            ModalAlert.fire({
                text: $.t('fs.invalid_name'),
                icon: "warning",
                confirmButtonText: $.t('general.ok'),
                customClass: {
                    confirmButton: "btn btn-primary"
                }
            });
            return;
        }

        $('#loading_message').text("");
        KTApp.showPageLoading();

        function executeRename() {
            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 == 202;
                }
            }).then(function (response) {
                taskStatusWaiter.wait({
                    taskID: response.data.message,
                    delay: 500
                }).then((result) => {
                    if (result.status == 200){
                        location.reload();
                    } else {
                        showRenameItemError(result.status, oldName);
                    }
                });
            }).catch(function (error) {
                let status = 0;
                if (error && error.response) {
                    status = error.response.status;
                }
                showRenameItemError(status, oldName);
            });
        }

        CheckExist.fire({
            operation: "move",
            files: [newName],
            path: '{{.CurrentDir}}'
        }).then((result)=>{
            if (result.error) {
                KTApp.hidePageLoading();
                ModalAlert.fire({
                    text: $.t('fs.rename.err_generic', { name: oldName }),
                    icon: "warning",
                    confirmButtonText: $.t('general.ok'),
                    customClass: {
                        confirmButton: "btn btn-primary"
                    }
                });
                return;
            }
            if (result.data.length > 0){
                KTApp.hidePageLoading();
                ModalAlert.fire({
                    text: $.t('fs.rename.err_exists', { name: oldName }),
                    icon: "warning",
                    confirmButtonText: $.t('general.ok'),
                    customClass: {
                        confirmButton: "btn btn-primary"
                    }
                });
                return;
            }
            executeRename();
        });
    }

    function showCreateNewFolder(sender) {
        if (sender == 0) {
            $('.new_folder_divider').removeClass("d-none");
            $('#file_manager_new_folder').removeClass("d-none");
            $('#errorMsg').addClass("d-none");
            let el = $('#file_manager_new_folder_input');
            el.val("");
            el.focus();
            return;
        }
        $('.dir_browser_folder_divider').removeClass("d-none");
        $('#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){
            $('.new_folder_divider').addClass("d-none");
            $('#file_manager_new_folder').addClass("d-none");
        } else {
            $('.dir_browser_folder_divider').addClass("d-none");
            $('#dirsbrowser_new_folder').addClass("d-none");
        }
    }

    function createNewFolder() {
        let errDivEl = $('#errorMsg');
        let errTxtEl = $('#errorTxt');
        let dirName = $("#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){
            setI18NData(errTxtEl, "fs.folder_name_required");
            errDivEl.removeClass("d-none");
            return;
        }
        if (dirName.includes("/")){
            setI18NData(errTxtEl, "fs.invalid_name");
            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 = "";
                if (error && error.response) {
                    switch (error.response.status) {
                        case 403:
                            errorMessage = "fs.create_dir.err_403";
                            break;
                        case 429:
                            errorMessage = "fs.create_dir.err_429";
                            break;
                    }
                }
                if (!errorMessage){
                    errorMessage = "fs.create_dir.err_generic";
                }
                setI18NData(errTxtEl, 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;
        let checkedDirs = [];
        $('#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;
            let name = f.name;
            let mkdirParents = "false";
            if (f.fullPath){
                name = f.fullPath;
                let dirName = name.substr(0, name.lastIndexOf("/"));
                if (!checkedDirs.includes(dirName)){
                    mkdirParents = "true";
                    checkedDirs.push(dirName);
                }
            }
            //{{- if .ShareUploadBaseURL}}
            uploadPath = '{{.ShareUploadBaseURL}}' + encodeURIComponent("/" + name)+"?mkdir_parents="+mkdirParents;
            //{{- else}}
            uploadPath = '{{.FileURL}}?path={{.CurrentDir}}' + encodeURIComponent("/" + name)+"&mkdir_parents="+mkdirParents;
            //{{- end}}
            let lastModified;
            try {
                lastModified = f.lastModified;
            } catch (e) {
                console.error("unable to get last modified time from file: " + e.message);
                lastModified = "";
            }

            let uploadTxt = f.name;
            if (files.length > 1){
                uploadTxt = $.t('fs.uploading', {
                    idx: index + 1,
                    total: files.length,
                    name: 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;
                if (error && error.response) {
                    switch (error.response.status) {
                        case 403:
                            errorMessage = "fs.upload.err_403";
                            break;
                        case 429:
                            errorMessage = "fs.upload.err_429";
                            break;
                    }
                }
                if (!errorMessage){
                    errorMessage = "fs.upload.err_generic";
                }
                index++;
                has_errors = true;
                setI18NData($('#errorTxt'), errorMessage);
                $('#errorMsg').removeClass("d-none");
                uploadFile();
            });
        }

        let filesArray = [];
        let dirsArray = [];
        if (files.length > 0){
            for (let i = 0; i < files.length; i++){
                if (files[i].fullPath){
                    let dirName = files[i].fullPath.split('/')[0];
                    if (!dirsArray.includes(dirName)){
                        dirsArray.push(dirName);
                    }
                    if (!filesArray.includes(dirName)){
                        filesArray.push(dirName);
                    }
                } else {
                    filesArray.push(files[i].name);
                }
            }
        }

        CheckExist.fire({
            operation: "upload",
            files: filesArray,
            path: "{{.CurrentDir}}"
        }).then((result)=> {
            if (result.error) {
                has_errors = true;
                setI18NData($('#errorTxt'), "fs.upload.err_generic");
                $('#errorMsg').removeClass("d-none");
                uploadFile();
                return;
            }
            let existingEntries = [];
            let fileOverwriteDirs = [];
            $.each(result.data, function (key, item) {
                if (item.type === "1" && !dirsArray.includes(item.name)) {
                    fileOverwriteDirs.push(item.name);
                } else {
                    existingEntries.push(item.name);
                }
            });
            if (fileOverwriteDirs.length > 0) {
                has_errors = true;
                setI18NData($('#errorTxt'), "fs.upload.err_dir_overwrite", {val: fileOverwriteDirs.join(", ")});
                $('#errorMsg').removeClass("d-none");
                uploadFile();
                return;
            }
            if (existingEntries.length > 0) {
                KTApp.hidePageLoading();
                ModalAlert.fire({
                    text: $.t('fs.upload.overwrite_text'),
                    items: existingEntries,
                    icon: "warning",
                    confirmButtonText: $.t('general.confirm'),
                    cancelButtonText: $.t('general.cancel'),
                    customClass: {
                        confirmButton: "btn btn-danger",
                        cancelButton: 'btn btn-secondary'
                    }
                }).then((result) => {
                    if (result.isConfirmed){
                        KTApp.showPageLoading();
                    } else {
                        has_errors = true;
                    }
                    uploadFile();
                });
                return;
            }
            uploadFile();
        });
    }

    var CheckExist = function () {
            var promiseResolve;

            function doCheck(operation, files, target) {
                let path = '{{.CheckExistURL}}?op='+encodeURIComponent(operation)+"&path="+target;
                axios.post(path, {
                    files: files
                }, {
                    headers: {
                        timeout: 15000,
                        'X-CSRF-TOKEN': '{{.CSRFToken}}'
                    },
                    validateStatus: function (status) {
                        return status == 200;
                    }
                }).then(function(response){
                    promiseResolve({
                        error: false,
                        data: response.data
                    });
                }).catch(function(error){
                    promiseResolve({
                        error: true
                    });
                });
            }

            return {
                fire: function (params) {
                    return new Promise(function (resolve, reject) {
                        promiseResolve = resolve;
                        doCheck(params.operation, params.files, params.path);
                    });
                }
            }
        }();

    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);
    }

    $(document).on("i18nshow", function(){
        KTDatatablesServerSide.init();

        var dropzone =  new Dropzone("#upload_files", {
            url: "{{.FilesURL}}?path={{.CurrentDir}}",
            paramName: "filenames",
            createImageThumbnails: false,
            maxFiles: null,
            maxFilesize: null,
            autoQueue: false,
            addRemoveLinks: false,
            autoProcessQueue: false,
            filesizeBase: 1000,
            previewTemplate: dzPreviewTemplate,
            init: function() {
                var dropzone = this;
                $("#upload_files_button").click(function(){
                   uploadFiles(dropzone.getAcceptedFiles());
                });
            }
        });

        dropzone.on("addedfile", file => {
            for (node of file.previewElement.querySelectorAll("[data-custom-size]")) {
                node.textContent = fileSizeIEC(file.size);
            }
            if (file.fullPath){
                for (var node of file.previewElement.querySelectorAll("[data-dz-name]")) {
                    node.textContent = file.fullPath;
                }
            }
        });

        var dropzoneEmpty =  new Dropzone("#upload_files_empty", {
            url: "{{.FilesURL}}?path={{.CurrentDir}}",
            paramName: "filenames",
            createImageThumbnails: false,
            maxFiles: null,
            maxFilesize: null,
            autoQueue: false,
            addRemoveLinks: false,
            autoProcessQueue: false,
            filesizeBase: 1000,
            previewTemplate: dzPreviewTemplate,
            init: function() {
                var dropzoneEmpty = this;
                $("#upload_files_empty_button").click(function(){
                   uploadFiles(dropzoneEmpty.getAcceptedFiles());
                });
            }
        });

        dropzoneEmpty.on("addedfile", file => {
            for (node of file.previewElement.querySelectorAll("[data-custom-size]")) {
                node.textContent = fileSizeIEC(file.size);
            }
            if (file.fullPath){
                for (var node of file.previewElement.querySelectorAll("[data-dz-name]")) {
                    node.textContent = file.fullPath;
                }
            }
        });

        $('#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-375px" data-kt-menu="true">
        <div class="card">
            <div class="card-header">
                <h3 class="card-title"><span data-i18n="fs.quota_usage.title" class="text-gray-700 fw-bold 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 data-i18n="fs.quota_usage.disk" 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">
                            <span {{if gt $percentage 0}}data-i18n="fs.quota_usage.size_percentage" data-i18n-options='{ "val": "{{$size}}", "percentage": {{$percentage}} }'{{else}}data-i18n="fs.quota_usage.size" data-i18n-options='{ "val": "{{$size}}" }'{{end}}></span>
                        </div>
                        {{- end}}
                        {{- if $files}}
                        {{- $percentage := .QuotaUsage.GetQuotaFilesPercentage}}
                        <div class="{{if .QuotaUsage.IsQuotaFilesLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">
                            <span {{if gt $percentage 0}}data-i18n="fs.quota_usage.files_percentage" data-i18n-options='{ "val": "{{$files}}", "percentage": {{$percentage}} }'{{else}}data-i18n="fs.quota_usage.files" data-i18n-options='{ "val": "{{$files}}" }'{{end}}></span>
                        </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 data-i18n="fs.quota_usage.transfer" 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">
                            <span {{if gt $percentage 0}}data-i18n="fs.quota_usage.total_percentage" data-i18n-options='{ "val": "{{$total}}", "percentage": {{$percentage}} }'{{else}}data-i18n="fs.quota_usage.total" data-i18n-options='{ "val": "{{$total}}" }'{{end}}>
                            </span>
                        </div>
                        {{- end}}
                        {{- if $download}}
                        {{$percentage := .QuotaUsage.GetDownloadTransferQuotaPercentage}}
                        <div class="{{if .QuotaUsage.IsDownloadTransferQuotaLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">
                            <span {{if gt $percentage 0}}data-i18n="fs.quota_usage.downloads_percentage" data-i18n-options='{ "val": "{{$download}}", "percentage": {{$percentage}} }'{{else}}data-i18n="fs.quota_usage.downloads" data-i18n-options='{ "val": "{{$download}}" }'{{end}}>
                            </span>
                        </div>
                        {{- end}}
                        {{- if $upload}}
                        {{$percentage := .QuotaUsage.GetUploadTransferQuotaPercentage}}
                        <div class="{{if .QuotaUsage.IsUploadTransferQuotaLow}}text-warning{{else}}text-gray-700{{end}} fw-semibold fs-6">
                            <span {{if gt $percentage 0}}data-i18n="fs.quota_usage.uploads_percentage" data-i18n-options='{ "val": "{{$upload}}", "percentage": {{$percentage}} }'{{else}}data-i18n="fs.quota_usage.uploads" data-i18n-options='{ "val": "{{$upload}}" }'{{end}}>
                            </span>
                        </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 data-i18n="fs.upload.text" class="modal-title">Upload files</h3>
                <div data-i18n="[aria-label]general.close" class="btn btn-icon btn-sm btn-active-light-primary" data-bs-dismiss="modal" aria-label="Close">
                    <i class="ki-solid ki-cross fs-2x text-gray-700"></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 mh-350px overflow-auto visibility-auto" 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 data-i18n="fs.upload.message" 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 data-i18n="general.cancel" type="button" class="btn btn-light me-5" data-bs-dismiss="modal">Cancel</button>
                <button data-i18n="general.submit" 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 data-i18n="[aria-label]general.close" class="btn btn-icon btn-sm btn-active-light-primary" data-bs-dismiss="modal" aria-label="Close">
                    <i class="ki-solid ki-cross fs-2x text-gray-700"></i>
                </div>
            </div>

            <div class="modal-body">
                <video id="video_player" width="100%" height="auto" controls preload="metadata">
                    <span data-i18n="general.html5_media_not_supported"></span>
                </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 data-i18n="[aria-label]general.close" class="btn btn-icon btn-sm btn-active-light-primary" data-bs-dismiss="modal" aria-label="Close">
                    <i class="ki-solid ki-cross fs-2x text-gray-700"></i>
                </div>
            </div>

            <div class="modal-body">
                <input id="rename_old_name" type="text" class="d-none"/>
                <div class="mb-10">
                    <label data-i18n="fs.rename.new_name" for="rename_new_name" class="form-label"></label>
                    <input id="rename_new_name" type="text" class="form-control"/>
                </div>
            </div>

            <div class="modal-footer border-0">
                <button data-i18n="general.cancel" type="button" class="btn btn-secondary me-5" data-bs-dismiss="modal">Cancel</button>
                <button data-i18n="general.confirm" 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 data-i18n="general.choose_target_folder" class="modal-title">
                    Choose target folder
                </h3>
                <div data-i18n="[aria-label]general.close" class="btn btn-icon btn-sm btn-active-light-primary" data-bs-dismiss="modal" aria-label="Close">
                    <i class="ki-solid ki-cross fs-2x text-gray-700"></i>
                </div>
            </div>

            <div class="modal-body">
                <div id="errorModalMsg" class="d-none rounded border-warning border border-dashed 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-solid ki-cross fs-2x text-gray-700"></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>
                            <span data-i18n="general.add"></span>
                        </button>
                    </div>
                </div>
                <div class="dir_browser_folder_divider py-2 d-none">
                    <hr>
                </div>
                <div id="dirsbrowser_new_folder" class="d-flex align-items-center 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 data-i18n="[placeholder]fs.create_folder_msg" 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-solid ki-cross fs-1"></i>
                    </button>
                </div>
                <div class="dir_browser_folder_divider py-2 d-none">
                    <hr>
                </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 data-i18n="general.name" 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 data-i18n="general.source_name" 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 data-i18n="general.target_folder" 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 data-i18n="general.dest_name" for="move_copy_name">Destination name</label>
                </div>

            </div>
            <div class="modal-footer border-0">
                {{- if .CanCopy }}
                <button id="id_copy_button" type="button" class="btn {{if .CanRename}}btn-light-primary me-5{{else}}btn-primary{{end}}" data-bs-dismiss="modal">
                    <span data-i18n="fs.copy.msg">Copy</span>
                </button>
                {{- end}}
                {{- if .CanRename }}
                <button id="id_move_button" type="button" class="btn btn-primary" data-bs-dismiss="modal">
                    <span data-i18n="fs.move.msg">Move</span>
                </button>
                {{- end}}
            </div>
        </div>
    </div>
</div>
{{- end}}
{{- end}}