Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drag&drop support for report file #32 - Done #38

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/GitHubCostVisualizer.Web/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
<p>Unsure of where your money is going with your Github account? Upload your recent Usage report from Github to get a visual on where your money is going</p>

<form asp-controller="Home" asp-action="Report" enctype="multipart/form-data">

<label>Github Usage File</label>
<div class="custom-file">
<input type="file" class="custom-file-input" asp-for="UploadFile">
<label class="custom-file-label" for="UploadFile">Choose file...</label>
<span class="text-danger" asp-validation-for="UploadFile"></span>
<div class="drop-zone">
<span class="drop-zone__prompt">Drop a Github usage file here or click to upload</span>
<input type="file" class="drop-zone__input" asp-for="UploadFile">
</div>
<span class="text-danger" asp-validation-for="UploadFile"></span>

<div class="alert alert-info mt-1">
Your uploaded file is never stored and processed in real-time only.
Expand All @@ -28,7 +26,8 @@
</form>

@section scripts{
<script>
<script>
handleFilePickers(".custom-file-input");
</script>
<script type="text/javascript" src="/js/dragdrop.js" asp-append-version="true"></script>
}
1 change: 1 addition & 0 deletions src/GitHubCostVisualizer.Web/Views/Shared/_Start.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<!-- Stylesheets -->
<link href="/css/style.min.css" rel="stylesheet" type="text/css" asp-append-version="true">
<link href="/css/all.min.css" rel="stylesheet" type="text/css" asp-append-version="true">
<link href="/css/dragdrop.css" rel="stylesheet" type="text/css" asp-append-version="true">

<!-- Javascript -->
<script type="text/javascript" src="/js/jquery.min.js" asp-append-version="true"></script>
Expand Down
48 changes: 48 additions & 0 deletions src/GitHubCostVisualizer.Web/wwwroot/css/dragdrop.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

.drop-zone {
max-width: 100%;
height: 200px;
padding: 25px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-family: "Quicksand", sans-serif;
font-weight: 500;
font-size: 20px;
cursor: pointer;
color: #cccccc;
border: 4px dashed #2286c9;
border-radius: 10px;
}

.drop-zone--over {
border-style: solid;
}

.drop-zone__input {
display: none;
}

.drop-zone__thumb {
width: 100%;
height: 100%;
border-radius: 10px;
overflow: hidden;
background-color: #4a8fbd;
background-size: cover;
position: relative;
}

.drop-zone__thumb::after {
content: attr(data-label);
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 5px 0;
color: #ffffff;
background: rgba(0, 0, 0, 0.75);
font-size: 14px;
text-align: center;
}
71 changes: 71 additions & 0 deletions src/GitHubCostVisualizer.Web/wwwroot/js/dragdrop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
document.querySelectorAll(".drop-zone__input").forEach((inputElement) => {
const dropZoneElement = inputElement.closest(".drop-zone");

dropZoneElement.addEventListener("click", (e) => {
inputElement.click();
});

inputElement.addEventListener("change", (e) => {
if (inputElement.files.length) {
updateThumbnail(dropZoneElement, inputElement.files[0]);
}
});

dropZoneElement.addEventListener("dragover", (e) => {
e.preventDefault();
dropZoneElement.classList.add("drop-zone--over");
});

["dragleave", "dragend"].forEach((type) => {
dropZoneElement.addEventListener(type, (e) => {
dropZoneElement.classList.remove("drop-zone--over");
});
});

dropZoneElement.addEventListener("drop", (e) => {
e.preventDefault();

if (e.dataTransfer.files.length) {
inputElement.files = e.dataTransfer.files;
updateThumbnail(dropZoneElement, e.dataTransfer.files[0]);
}

dropZoneElement.classList.remove("drop-zone--over");
});
});

/**
* Updates the thumbnail on a drop zone element.
*
* @param {HTMLElement} dropZoneElement
* @param {File} file
*/
function updateThumbnail(dropZoneElement, file) {
let thumbnailElement = dropZoneElement.querySelector(".drop-zone__thumb");

// First time - remove the prompt
if (dropZoneElement.querySelector(".drop-zone__prompt")) {
dropZoneElement.querySelector(".drop-zone__prompt").remove();
}

// First time - there is no thumbnail element, so lets create it
if (!thumbnailElement) {
thumbnailElement = document.createElement("div");
thumbnailElement.classList.add("drop-zone__thumb");
dropZoneElement.appendChild(thumbnailElement);
}

thumbnailElement.dataset.label = file.name;

// Show thumbnail for image files
if (file.type.startsWith("image/")) {
const reader = new FileReader();

reader.readAsDataURL(file);
reader.onload = () => {
thumbnailElement.style.backgroundImage = `url('${reader.result}')`;
};
} else {
thumbnailElement.style.backgroundImage = null;
}
}
Loading