153 lines
5.6 KiB
JavaScript
153 lines
5.6 KiB
JavaScript
/********************
|
|
* Diagram Import JS *
|
|
*********************/
|
|
|
|
function initDiagramImport() {
|
|
const dialogElement = document.getElementById("diagram-import");
|
|
const fileInput = document.getElementById("diagram-import-input");
|
|
const okButton = document.getElementById("diagram-import-ok-btn");
|
|
const errorMessageElement = document.getElementById("diagram-import-error-message");
|
|
|
|
function openDialog(isOpenManually = true) {
|
|
setVisibility(dialogElement, true, true);
|
|
dialogElement.dataset.isOpenManually = isOpenManually.toString();
|
|
// reset or clear file input
|
|
fileInput.value = "";
|
|
onFileInputChange(fileInput);
|
|
}
|
|
function closeDialog() {
|
|
fileInput.value = ""; // reset or clear
|
|
onFileInputChange(fileInput);
|
|
dialogElement.removeAttribute("data-is-open-manually");
|
|
setVisibility(dialogElement, false);
|
|
}
|
|
|
|
function onFileInputChange(fileInput) {
|
|
errorMessageElement.innerText = "";
|
|
okButton.disabled = fileInput.files?.length < 1;
|
|
}
|
|
|
|
function checkFileLocally(file) {
|
|
function getImageFileType({name, type}) {
|
|
const supported = ["png", "svg"];
|
|
// get type by mime type
|
|
let fileType = supported.filter(t => type.toLowerCase().indexOf(t) !== -1)[0];
|
|
if (fileType) return fileType;
|
|
// fallback: get type by filename extension
|
|
if (name.indexOf(".") === -1) return undefined;
|
|
const ext = name.substring(name.lastIndexOf(".")+1).toLowerCase();
|
|
return supported.filter(t => ext === t)[0];
|
|
}
|
|
function isDiagramCode({name, type}) {
|
|
// get type by mime type
|
|
let supported = ["plain", "text", "plantuml", "puml"];
|
|
if (supported.filter(t => type.toLowerCase().indexOf(t) !== -1).length > 0) {
|
|
return true;
|
|
}
|
|
// fallback: get type by filename extension
|
|
if (name.indexOf(".") === -1) return false;
|
|
const ext = name.substring(name.lastIndexOf('.')+1).toLowerCase();
|
|
supported = ["txt", "puml", "plantuml"];
|
|
return supported.filter(t => ext === t).length > 0;
|
|
}
|
|
|
|
const type = getImageFileType(file);
|
|
const isCode = type === undefined ? isDiagramCode(file) : false;
|
|
if (!type && !isCode) {
|
|
errorMessageElement.innerText = "File not supported. " +
|
|
"Only PNG and SVG diagram images as well as PlantUML code text files are supported."
|
|
}
|
|
return { type, isDiagramCode: isCode, valid: type || isCode };
|
|
}
|
|
|
|
function importDiagram(file, fileCheck) {
|
|
function loadDiagram(code) {
|
|
setEditorValue(document.editor, code);
|
|
}
|
|
function requestMetadata(file) {
|
|
const fd = new FormData();
|
|
fd.append("diagram", file, file.name);
|
|
return makeRequest("POST", "metadata", {
|
|
data: fd,
|
|
responseType: "json",
|
|
headers: { "Accept": "application/json" },
|
|
});
|
|
}
|
|
|
|
dialogElement.classList.add("wait");
|
|
return new Promise((resolve, reject) => {
|
|
if (fileCheck.type) {
|
|
// upload diagram image, get meta data from server and load diagram from result
|
|
requestMetadata(file).then(
|
|
metadata => { loadDiagram(metadata.decoded); resolve(); },
|
|
({ response }) => { errorMessageElement.innerText = response.message || response; reject(); }
|
|
);
|
|
} else if (fileCheck.isDiagramCode) {
|
|
// read code (text) file
|
|
const reader = new FileReader();
|
|
reader.onload = event => loadDiagram(event.target.result);
|
|
reader.readAsText(file);
|
|
resolve();
|
|
} else {
|
|
// this error should already be handled.
|
|
errorMessageElement.innerText = "File not supported. " +
|
|
"Only PNG and SVG diagram images as well as PlantUML code text files are supported.";
|
|
reject();
|
|
}
|
|
}).then(() => closeDialog(), () => {}).finally(() => dialogElement.classList.remove("wait"));
|
|
}
|
|
|
|
function onGlobalDragEnter(event) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
if (!isVisible(dialogElement)) {
|
|
openDialog(false);
|
|
}
|
|
}
|
|
|
|
function onFileInputDragOver(event) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
if (event.dataTransfer !== null) {
|
|
event.dataTransfer.dropEffect = "copy";
|
|
}
|
|
}
|
|
function onFileInputDrop(event) {
|
|
function stop() {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
const files = event.dataTransfer.files || event.target.files;
|
|
if (!files || files.length < 1) {
|
|
return stop();
|
|
}
|
|
const file = files[0];
|
|
const fileCheck = checkFileLocally(file);
|
|
if (!fileCheck.valid) {
|
|
return stop();
|
|
}
|
|
if (dialogElement.dataset.isOpenManually === "true") {
|
|
return; // let file input handle this event => no `stop()`!
|
|
}
|
|
// drop and go - close modal without additional ok button click
|
|
stop();
|
|
importDiagram(file, fileCheck);
|
|
}
|
|
|
|
// global drag&drop events
|
|
window.addEventListener("dragenter", onGlobalDragEnter, false);
|
|
// diagram import dialog drag&drop events
|
|
fileInput.addEventListener("dragenter", event => event.target.classList.add("drop-able"), false);
|
|
fileInput.addEventListener("dragover", onFileInputDragOver, false);
|
|
fileInput.addEventListener("dragexit", event => event.target.classList.remove("drop-able"), false);
|
|
fileInput.addEventListener("drop", onFileInputDrop, false);
|
|
fileInput.addEventListener("change", event => onFileInputChange(event.target));
|
|
// ok button
|
|
okButton.addEventListener("click", () => {
|
|
const file = fileInput.files[0]; // should be always a valid file
|
|
importDiagram(file, checkFileLocally(file)); // otherwise button should be disabled
|
|
});
|
|
// register model listeners
|
|
registerModalListener("diagram-import", openDialog, closeDialog);
|
|
}
|