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

Feat file drag and drop #10

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 5 additions & 2 deletions internal/app/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ func (a *App) ContentHandler(w http.ResponseWriter, r *http.Request) {
}

func (a *App) uploadFile(w http.ResponseWriter, r *http.Request) {
name := r.PostFormValue("name")
file, header, err := r.FormFile("file")
// name := r.PostFormValue("name")
name := header.Filename
if err != nil {
http.Error(w, "Error getting file: "+err.Error(), http.StatusInternalServerError)
return
}
fmt.Println("Uploading file", name)
fmt.Println("...", file)

buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, file); err != nil {
Expand Down Expand Up @@ -82,7 +85,7 @@ func (a *App) uploadFile(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Error creating PR " + err.Error()))
return
}

w.Write([]byte("File Uploaded"))
return
}
Expand Down
156 changes: 134 additions & 22 deletions templates/content.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<!-- Add Bootstrap JavaScript and Popper.js -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

{{ if .HasReadme }}
<div class="border-foreground border rounded-md p-4 mb-2">
<p class="markdown">{{ .Readme }}</p>
Expand All @@ -24,65 +28,173 @@
{{ $currentLink := "/" }}

{{ range $idx, $part := $parts }}
{{ if ne $part "" }}
{{ $currentLink = print $currentLink $part "/" }}
{{ if $currentLink | eq "/content/" }}
{{ $names = append $names "HOME" }}
{{ else }}
{{ $names = append $names $part }}
{{ end }}
{{ $links = append $links $currentLink }}
{{ end }}
{{ if ne $part "" }}
{{ $currentLink = print $currentLink $part "/" }}
{{ if $currentLink | eq "/content/" }}
{{ $names = append $names "HOME" }}
{{ else }}
{{ $names = append $names $part }}
{{ end }}
{{ $links = append $links $currentLink }}
{{ end }}
{{ end }}

{{ template "breadcrumb" (dict "Names" $names "Links" $links) }}
</div>

<!-- -->

<ul
class="border divide-y divide-border border-border rounded-lg first-of-type:rounded-t-lg mb-4"
>
<ul class="border divide-y divide-border border-border rounded-lg first-of-type:rounded-t-lg mb-4">
<!-- prettier-ignore -->
{{ range .Items }}
{{ if .IsTree }}
{{ if .IsTree }}
<li class="w-full px-4 py-2">
<a href="{{ .Link }}">{{ .Name }}</a>
</li>
<!-- prettier-ignore -->
{{ else }}
{{ $btnc := "w-full px-4 py-2" }}
{{ template "dropdown" (dict "Menu" (dict "Chat" .Link "Download" .Download) "IsLink" true "Title" .Name "TitleId" .Name "ButtonClass" $btnc) }}
{{ else }}
{{ $btnc := "w-full px-4 py-2" }}
{{ template "dropdown" (dict "Menu" (dict "Chat" .Link "Download" .Download) "IsLink" true "Title" .Name "TitleId"
.Name "ButtonClass" $btnc) }}
{{ end }} {{ end }}
</ul>

<form id="upload-form" class="h-20" enctype="multipart/form-data">
<input type="text" name="name" placeholder="Name" />
<input type="file" name="file" placeholder="File Input" />
<button type="submit">Add</button>
<input type="file" name="file" placeholder="File Input" style="display: none"/>

<!-- File drag and drop area -->
<div id="drop-zone" class="border border-dashed border-gray-400 p-8 mt-4 h-40 w-full cursor-pointer flex justify-center items-center text-center" style="text-align: center;">
<span id="drop-zone-text">
Drag and drop files or click to choose files<br>
PDF files only (maximum size: 8MB)
</span>
</div>

<!-- The file you choose and the submit button -->
<div class="flex items-center space-x-2">
<div id="file-name"></div>
<button type="submit" class="bg-[#39bff8] border-none text-white py-1 px-4 text-center font-medium text-lg m-1 cursor-pointer hidden hover:bg-[#0056b3] active:bg-[#004085]" id="add-button">Add</button>
</div>

{{ template "upload-modal" }}

</form>
{{ template "upload-script" }} {{ template "upload-modal" }}
{{ template "upload-script" }}

<!-- -->

<!-- -->

{{ define "upload-script" }}
<script>
const uploadForm = document.getElementById("upload-form");
const dropZone = document.getElementById("drop-zone");
const fileInput = uploadForm.querySelector('input[type="file"]');
const fileNameDisplay = document.getElementById("file-name");
const addButton = document.getElementById("add-button");

// if the user has already selected a file, show the add button
function toggleAddButton() {
addButton.style.display = fileNameDisplay.textContent !== "" ? "inline-block" : "none";
}

dropZone.addEventListener('click', () => {
fileInput.click();
console.log("here!!!");
});

// after clicking the file in the popup folder, check if the file is a PDF and within the size limit,
// then show the file name and the add button
fileInput.addEventListener('change', () => {
const file = fileInput.files[0];
if (file) {
if (file.type !== "application/pdf") {
alert("Only PDF files are allowed.");
return;
}
if (file.size > 8 * 1024 * 1024) { // 8MB in bytes
alert("File size exceeds 8MB.");
return;
}
fileNameDisplay.textContent = file.name; // Display file name
console.log("click current file is : " + file.name);
toggleAddButton();
}
});

// Prevent default drag behaviors
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, preventDefaults, false);
document.body.addEventListener(eventName, preventDefaults, false);
});

function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}

// Highlight drop area when item is dragged over it
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, () => {
dropZone.classList.add('border-blue-500', 'bg-blue-100');
}, false);
});

// Remove drop highlight
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, () => {
dropZone.classList.remove('border-blue-500', 'bg-blue-100');
}, false);
});

// Handle dropped files
dropZone.addEventListener('drop', handleDrop, false);

function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;

// Check if the file is a PDF and within the size limit
const file = files[0];
if (file) {
if (file.type !== "application/pdf") {
alert("Only PDF files are allowed.");
return;
}
if (file.size > 8 * 1024 * 1024) { // 8MB in bytes
alert("File size exceeds 8MB.");
return;
}

fileInput.files = files;
fileNameDisplay.textContent = file.name; // Display file name
console.log("drop current file is : " + file.name);
toggleAddButton();
}
}

// after the Add button is clicked, show the modal and send the file to the server
uploadForm.addEventListener("submit", async (e) => {
e.preventDefault();

const uploadM = new bootstrap.Modal(
document.getElementById("upload-modal")
);
uploadM.show();

document.getElementById("upload-modal-body").innerHTML = "Loading...";

const formData = new FormData(uploadForm);
const res = await fetch(window.location.href, {
method: "POST",
body: formData,
});
const message = await res.text();
document.getElementById("upload-modal-body").innerHTML = message;
alert(message);
document.getElementById("upload-modal-body").innerHTML = "";
fileInput.value = "";
fileNameDisplay.textContent = "";
toggleAddButton();
});
</script>
{{ end }}
Expand All @@ -97,4 +209,4 @@
</div>
</div>
</div>
{{ end }}
{{ end }}