import { UiElement } from "../../../ui/UiElement.js";
import { FileDropTarget } from "../../../ui/dnd/FileDropTarget.js";
import { FileBinder } from "../binder/FileBinder.js";
import "./FileUi.css";
export { FileUi };
/**
* Ui class for importing File based layers
*
* @memberof vef.map.importer.ui
*/
class FileUi extends UiElement {
title = "File";
classes = ["importer-ui", "file-ui"];
html = `
<div class="url-input-form">
<input spellcheck="false" type="text" placeholder="Insert File URL..." class="url-input"/><!--
--><button class="url-input-button"><i class="fas fa-plus"></i></button>
</div>
<div class="file-list"></div>
<p class="file-drop-area">
<i class="fas fa-upload"></i><br/>
Drop Files here<br/>
or<br/>
<a href="#" class="browse-file-link">Browse Files</a><br/><br/>
<i style="font-size:13px; color:#BBB;">Tab/Comma-Separated and GeoJSON Files are Supported</i>
</p>
<div class="button-group">
<button class="btn-add" disabled="true"><i class="fas fa-plus"></i> Add</button>
</div>
`;
constructor(target, fileOptions) {
super(target, {
"add_layers": [],
"close": []
});
this.fileOptions_ = Object.assign({}, fileOptions);
this.files_ = [];
this.setHtml(this.html);
this.setClass(this.classes);
this.initEvents_();
}
addFile_(file) {
if (!(file instanceof File) && (typeof file != "string")) return;
const filename = (typeof file == "string") ? file : file.name;
const type = FileBinder.guessFileType(filename);
const list = this.query(".file-list");
const entry = document.createElement("div");
entry.classList.add("file-list-entry");
entry.innerHTML = `
<i class="fas fa-times"></i>
<div class="filename"></div>
<div class="status"></div>
<select class="type-dropdown">
<option value="geojson">GeoJSON</option>
<option value="csv">CSV</option>
</select>
`;
entry.querySelector(".filename").innerText = filename;
entry.querySelector(".type-dropdown").value = type;
list.appendChild(entry);
const item = {
type: type,
filename: filename,
status: "new",
file: file,
element: entry
};
entry.querySelector(".fas.fa-times").onclick = () => {
entry.remove();
const index = this.files_.indexOf(item);
if (index > -1) this.files_.splice(index, 1);
this.checkAddButtonState_();
};
this.files_.push(item);
this.checkAddButtonState_();
}
checkAddButtonState_() {
let enabled = false;
for (let i = 0; i < this.files_.length; ++i) {
const file = this.files_[i];
if (["new", "error"].includes(file.status)) {
enabled = true;
break;
}
}
this.query(".button-group .btn-add").disabled = !enabled;
}
initEvents_() {
this.query(".browse-file-link").addEventListener("click", e => {
e.preventDefault();
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.onchange = fileEvent => {
for (let i = 0; i < fileEvent.target.files.length; ++i) {
this.addFile_(fileEvent.target.files[i]);
}
};
fileInput.click();
});
new FileDropTarget(this.query(".file-drop-area")).on("drop", files => {
for (let i = 0; i < files.length; ++i) {
this.addFile_(files[i]);
}
});
this.query(".button-group .btn-add").addEventListener("click", e => {
this.query(".button-group .btn-add").disabled = true;
this.apply();
});
const urlInput = this.query(".url-input");
const inputListener = () => {
if (urlInput.value.length > 0) {
this.addFile_(urlInput.value);
urlInput.value = "";
}
}
this.query(".url-input-button").onclick = inputListener;
urlInput.onkeydown = e => {
// "enter" key
if (e.which == 13) inputListener();
};
}
apply() {
const promises = [];
const result = [];
let errors = false;
for (let i = 0; i < this.files_.length; ++i) {
const file = this.files_[i];
if (file.status == "success") continue;
const promise = FileBinder.loadFileLayer(file.file, this.fileOptions_, file.element.querySelector(".type-dropdown").value);
promises.push(promise);
const statusIcon = file.element.querySelector(".status");
statusIcon.innerHTML = '<i style="color:var(--primary-color);" class="fas fa-spinner fa-spin fa-fw"></i>'
promise.then(data => {
if (data) {
file.status = "success";
statusIcon.innerHTML = '<i style="color:green;" class="fas fa-check"></i>';
result.push(data);
} else {
errors = true;
file.status = "error";
statusIcon.innerHTML = '<i title="could not load layers" style="color:red;" class="fas fa-exclamation-triangle"></i>'
}
}).catch(error => {
console.warn(error);
});
}
Promise.all(promises).then(() => {
this.checkAddButtonState_();
if (result.length > 0) this.fire("add_layers", result)
if (!errors) {
this.reset()
this.fire("close");
}
});
}
reset() {
this.query(".file-list").innerHTML = "";
this.files_ = [];
this.checkAddButtonState_();
}
}