tampermonkey/src/60-cp-files.js
2026-08-15 19:12:05 +03:00

381 lines
12 KiB
JavaScript

async function sendFileDeleted(inputName, fileInputVariant = null) {
let formData = new FormData()
let normalInputName = fileInputVariant !== null ? fileInputs[inputName][fileInputVariant] : fileInputs[inputName]
formData.set(`cp[id]`, document.querySelector("input[name='cp[id]']").value)
formData.set(`cp[${normalInputName}]`, "-1")
let result = await updatePoint(formData)
try {
console.log(result.ok)
}
catch (e) {
console.log(e)
}
}
function parsePurpose(cell) {
return cell?.querySelector("td:nth-child(2)")?.innerHTML.match(/для[^\|]+/g)?.[0].trim()
}
function parsefileInputVariant(cell) {
return Object.keys(fileInpitVariants).find(key => fileInpitVariants[key] === parsePurpose(cell))
}
function addDisplayedFile(inputName, type, file, preview, removeLink, removedFilesLinks, variant = null) {
if (!inputName || !file || !removeLink) return
let fileListContainer
if (variant !== null) {
if (inputName == "attachment1" || inputName == "attachment4") {
if (variant == "l") {
fileListContainer = document.querySelector(`[data-container="${fileInputs[inputName][variant]}"] .file-list-container`)
}
else if (variant == "h") {
let filesContainer = document.querySelector(`[data-container="${fileInputs[inputName].h}"]`)
fileListContainer = getFileListContainer(filesContainer)
}
}
}
let input = document.querySelector(`input[name="${inputName}\[\]"]`)
fileListContainer ??= input.parentElement.parentElement.querySelector(".file-list-container")
let fileContainer = Tag.div({
classes: "file-container"
})
const displayedFile = Tag.make(type ?? "a", {
classes: "preview-small"
})
if (type == "img") {
displayedFile.src = preview
displayedFile.dataset.origin = file
displayedFile.addEventListener("click", () => {
let dialog = document.querySelector("dialog")
makeSwiper(dialog, fileListContainer, file)
dialog.showModal()
})
}
else if (type == "audio") {
displayedFile.src = file
displayedFile.setAttribute("controls", "")
}
else {
displayedFile.href = file
displayedFile.textContent = "Файл"
}
let fileButtonsContainer = Tag.div({
classes: "file-buttons-container"
})
fileButtonsContainer.append(makeDownloadLink(/[^/]*$/.exec(new URL(file).pathname)[0], file))
let deleteButton = Tag.button({
type: "button",
classes: "button-delete",
textContent: "x",
on: {
click: async e => {
if (!confirm("Точно?")) return
await fetch(removeLink)
await sendFileDeleted(inputName, variant)
removedFilesLinks.push(removeLink)
fileListContainer.removeChild(fileContainer)
}
}
})
fileButtonsContainer.append(deleteButton)
fileContainer.append(displayedFile)
fileContainer.append(fileButtonsContainer)
fileListContainer.append(fileContainer)
}
function dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[arr.length - 1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
}
function getHtmlElementByFileType(file) {
const htmlElementsForTypes = {
"image/": "img",
"audio/": "audio"
}
let res = "div"
for (const [type, el] of Object.entries(htmlElementsForTypes)) {
if (file.type.startsWith(type)) {
res = el
break
}
}
let el = Tag.make(res)
if (res == "audio") {
el.setAttribute("controls", "")
}
return el
}
function makeHandleFilesFunc() {
let storedFiles = []
return function () {
let dt = new DataTransfer()
if (storedFiles.length) {
for (const oldFile of storedFiles) {
let oldFileObj = dataURLtoFile(oldFile.data, oldFile.name)
dt.items.add(oldFileObj)
}
}
for (let i = 0; i < this.files.length; i++) {
const file = this.files[i]
dt.items.add(file)
let variant = this.parentElement.querySelector('input[type="radio"]:checked')?.value
let fileListContainer
if (variant) {
let [_, filesContainer] = getContainersByVariant(variant, getAttachmentIndex(this))
fileListContainer = getFileListContainer(filesContainer)
}
else {
fileListContainer = this.parentElement.parentElement.querySelector(".file-list-container")
}
let fileContainer = Tag.div({
classes: "file-container file-container-new"
})
const displayedFile = getHtmlElementByFileType(file)
displayedFile.classList.add("preview")
displayedFile.file = file
displayedFile.addEventListener("click", () => {
let dialog = document.querySelector("dialog")
makeSwiper(dialog, fileListContainer, displayedFile.src)
dialog.showModal()
})
let fileButtonsContainer = Tag.div({
classes: "file-buttons-container"
})
let downloadLink = makeDownloadLink(file.name)
fileButtonsContainer.append(downloadLink)
let deleteButton = Tag.button({
classes: "button-delete",
textContent: "x",
type: "button",
on: {
click: e => {
let index = [...fileContainer.parentElement.children].indexOf(fileContainer)
if (!confirm("Точно?")) return
storedFiles.splice(storedFiles.length - this.files.length + index, 1)
let rdt = new DataTransfer()
for (const file of this.files) {
rdt.items.add(file)
}
rdt.items.remove(index)
this.files = rdt.files
fileContainer.parentElement.removeChild(fileContainer)
}
}
})
fileButtonsContainer.append(deleteButton)
fileContainer.append(displayedFile)
fileContainer.append(fileButtonsContainer)
fileListContainer.append(fileContainer)
const reader = new FileReader()
reader.onload = (e) => {
displayedFile.src = e.target.result
downloadLink.setAttribute("href", displayedFile.src)
storedFiles.push({ data: displayedFile.src, name: file.name })
}
reader.readAsDataURL(file)
}
this.files = dt.files
}
}
let prettifyFiles = (function () {
let executed = false
return function (insertedFileRows, removedFilesLinks) {
if (executed) return
executed = true
document.querySelector("#new").querySelectorAll("input[type=file]").forEach((element, index) => {
element.id = `input-file-${index}`
element.setAttribute("multiple", "multiple")
element.dataset.index = index
let pseudoInput = Tag.make("label", {
classes: "custom-file-upload",
_for: element.id,
textContent: "+"
})
element.parentElement.insertBefore(pseudoInput, element)
element.parentElement.parentElement.append(makeFileListContainer())
element.addEventListener("change", makeHandleFilesFunc(), false)
})
moveFileInputValues(insertedFileRows, removedFilesLinks)
}
})()
function saveInputValues(from) {
let fromInputs = [...from.querySelectorAll("input, textarea")]
let result = new Map()
for (const fromEl of fromInputs) {
result.set(fromEl, fromEl.type == "radio" ? fromEl.checked : fromEl.value)
}
return result
}
function setInputValues(to, values) {
let toInputs = [...to.querySelectorAll("input, textarea")]
for (const [fromEl, value] of values) {
let currentToInput = toInputs.find(toEl =>
toEl.type !== 'file' &&
toEl.type === fromEl.type &&
toEl.name === fromEl.name &&
toEl.id === fromEl.id &&
(toEl.type !== "radio" || toEl.value === fromEl.value)
)
if (currentToInput) {
currentToInput.checked = fromEl.checked
currentToInput.value = fromEl.value
}
}
}
function moveFileInputValues(insertedFileRows, removedFilesLinks) {
for (const [inputRowIndex, rows] of insertedFileRows) {
for (const row of rows) {
let fileInput = null, type = null, fileUrl = null, deleteUrl = null, preview = null
if (row.querySelector("img")) {
type = "img"
fileUrl = row.querySelector("td:first-child a").href
preview = row.querySelector("img").src
}
else if (row.querySelector("audio")) {
type = "audio"
fileUrl = row.querySelector("audio").src
}
else {
fileUrl = row.querySelector("td:first-child a").href
}
deleteUrl = row.querySelector("td:nth-child(2) a").href
if (inputRowIndex == 23) {
fileInput = "attachment1"
}
else if (inputRowIndex == 27) {
fileInput = "attachment4"
}
else if (inputRowIndex == 31) {
fileInput = "attachment2"
}
else if (inputRowIndex == 35) {
fileInput = "attachment3"
}
else {
console.log(inputRowIndex)
return
}
let variant = parsefileInputVariant(row)
addDisplayedFile(fileInput, type, fileUrl, preview, deleteUrl, removedFilesLinks, variant)
}
}
}
function moveNewFilesOnVariantChange() {
document.querySelectorAll(`input[name^="new_file_type"]`).forEach(el => el.addEventListener("change", function () {
let attachmentIndex = getAttachmentIndex(this)
let [from, to] = getContainersByVariant(this.value, attachmentIndex)
let newFiles = [...from.querySelectorAll(`.file-container-new`)]
for (const newFile of newFiles) {
getFileListContainer(to).append(newFile)
}
}))
}
function removeDeletedFilesFromUglyVersion(removeLink) {
let shortHref = removeLink.split("/").at(-1)
document.querySelector(`tr:has(a[href="${shortHref}"])`).remove()
}
function moveInputValues(form, was, became) {
let inputValues = saveInputValues(was)
form.removeChild(was)
form.append(became)
setInputValues(became, inputValues)
createSendButtons()
}
function prettifyEditCpForm(form, was, became, insertedFileRows, removedFilesLinks) {
moveInputValues(form, was, became)
prettifyFiles(insertedFileRows, removedFilesLinks)
moveNewFilesOnVariantChange()
$("#cps_main").select2()
makeCoordinatesLinks()
}
function uglifyEditCpForm(form, was, became, removedFilesLinks) {
moveInputValues(form, was, became)
for (const removedFileLink of removedFilesLinks) {
removeDeletedFilesFromUglyVersion(removedFileLink)
}
}
function addUglyDeleteListener() {
let links = [...document.querySelectorAll("a[href*='del_stored']")]
for (const link of links) {
let shortHref = link.href.split("/").at(-1)
let fileInput = document.querySelector(`tr:has(a[href$="${shortHref}"]) ~ tr:has(input[type="file"]) input[type="file"]`)
let fileInputVariant = parsefileInputVariant(document.querySelector(`tr:has(a[href$="${shortHref}"])`))
link.addEventListener("click", async e => {
e.preventDefault()
if (!confirm("Точно?")) return
await sendFileDeleted(fileInput.name.split("[")[0], fileInputVariant)
location.href = link.href
})
}
}