1
0
mirror of https://github.com/gusaul/grpcox.git synced 2024-12-26 10:50:11 +00:00
grpcox/index/js/proto.js
2021-02-05 17:21:41 +01:00

166 lines
5.6 KiB
JavaScript

let protoMap;
let showCollection;
// IIFE to setup event listener
(function () {
// add event listener on proto checkbox
// if checked the uploader and proto collection view will be displayed
// also the grpc reflection will use given proto instead of server reflection
const protoSwitch = document.getElementById("local-proto");
protoSwitch.addEventListener("change", function(event) {
const { checked } = event.target;
toggleDisplayProtoInput(checked);
});
// add event listener on upload proto file
// uploaded file extension will be checked, only those with *.proto will be processed
// add successful file to protoMap to be displayed
const protoUploader = document.getElementById("proto-file");
protoUploader.addEventListener("change", handleProtoUpload, false);
// add event listener on toggle proto collection display
// it will show / hide the proto collection
const protoCollectionToggle = document.getElementById("proto-collection-toggle");
protoCollectionToggle.addEventListener("click", toggleDisplayProtoCollection);
// init map to handle proto files
// every proto files will be unique to their name
protoMap = new Map();
// set proto collection display status to true
// by default the collection will be shown
showCollection = true;
}());
// toggle proto files display
// displaying upload button
function toggleDisplayProtoInput(show) {
const style = show ? "display: block" : "display: none";
const protoInput = document.getElementById("proto-input");
protoInput.removeAttribute("style");
protoInput.style.cssText = style;
}
// toggle proto files collection
// displaying uploaded protos collection
function toggleDisplayProtoCollection() {
const protoCollection = document.getElementsByClassName("proto-collection")[0];
protoCollection.removeAttribute("style");
const protoToggle = document.getElementById("proto-collection-toggle");
let collectionStyle = "";
let toggleText = protoToggle.innerHTML;
if (showCollection) {
collectionStyle = "display: none";
toggleText = toggleText.replace("Hide", "Show");
} else {
collectionStyle = "display: block";
toggleText = toggleText.replace("Show", "Hide");
}
protoCollection.style.cssText = collectionStyle;
protoToggle.innerHTML = toggleText;
showCollection = !showCollection;
}
// handling file upload event
// add uploaded files to protoMap to avoid duplication, on file with same name the older
// file will be replaced with the latest
// if the file isn't available before, add DOM element for UI representation
// file without *.proto won't be processed
function handleProtoUpload() {
const files = this.files;
for (const file of files) {
if (!file.name.endsWith(".proto") && !file.name.endsWith(".protoset")) {
continue;
}
if (!protoMap.has(file.name)) {
addProtoItem(file.name, file.size);
}
protoMap.set(file.name, file);
}
}
// adding proto item to proto collection view
// give visual representation to user and access to remove unwanted uploaded files
function addProtoItem(name, size) {
const protoItem = createProtoItem(name, size);
const collection = document.getElementsByClassName("proto-collection")[0];
collection.appendChild(protoItem);
}
// create dom element for proto item
// every item will be given id corresponding to it's name for easier access
function createProtoItem(name, size) {
const item = document.createElement("div");
item.classList.add("proto-item");
item.id = name;
const icon = document.createElement("img");
icon.src = "img/file.png";
icon.alt = "file icon";
icon.classList.add("proto-icon");
item.appendChild(icon);
const desc = createProtoItemDesc(name, size);
item.appendChild(desc);
return item;
}
// create dom element for proto item description
function createProtoItemDesc(name, size) {
const desc = document.createElement("div");
desc.classList.add("proto-desc");
const caption = document.createElement("span");
caption.classList.add("proto-caption");
const captionText = document.createTextNode(name.length > 15 ?
name.substring(0, 12) + "..." :
name);
caption.appendChild(captionText);
desc.appendChild(caption);
const sizeDOM = document.createElement("span");
sizeDOM.classList.add("proto-size");
const sizeText = document.createTextNode(size > 1000 ?
`${size/1000}kb` :
`${size}b`);
sizeDOM.appendChild(sizeText);
desc.appendChild(sizeDOM);
const remove = document.createElement("button");
remove.classList.add("btn", "btn-sm", "proto-remove");
remove.addEventListener("click", function() {removeProtoItem(name);});
const removeIcon = document.createElement("i");
removeIcon.classList.add("fa", "fa-trash");
remove.appendChild(removeIcon);
const removeText = document.createTextNode(" remove");
remove.appendChild(removeText);
desc.appendChild(remove);
return desc;
}
// remove proto item based on it's ID
function removeProtoItem(name) {
const item = document.getElementById(name);
item.parentNode.removeChild(item);
protoMap.delete(name);
}
// fetch all proto from protoMap
// compose it into formData to make it easier to send via ajax
function getProtos() {
const formData = new FormData();
for (const proto of protoMap.values()) {
formData.append("protos", proto, proto.name);
}
return formData;
}