Compare commits
6 Commits
213f90a0b1
...
224e4a3e1c
Author | SHA1 | Date |
---|---|---|
mark.dev | 224e4a3e1c | |
mark.dev | 742e2dda4e | |
Ben Visness | c36ae9d91b | |
giggs | 85c8c92a0c | |
Ben Visness | 1f731a17c5 | |
Ben Visness | 608235ee29 |
|
@ -0,0 +1,239 @@
|
|||
/* Requires base64.js
|
||||
|
||||
Usage: setupMarkdownUpload(eSubmit, eFileInput, eUploadBar, eText, doMarkdown, maxFileSize, uploadUrl)
|
||||
eSubmit is the element of the button to submit/save the markdown changes. It
|
||||
will be disabled and tell users files are uploading while uploading is
|
||||
happening.
|
||||
eFileInput is the <input type="file">
|
||||
eUploadBar usually looks like
|
||||
<div class="upload_bar flex-grow-1">
|
||||
<div class="instructions">
|
||||
Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them.
|
||||
</div>
|
||||
<div class="progress flex">
|
||||
<div class="progress_text mr3"></div>
|
||||
<div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div>
|
||||
</div>
|
||||
</div>
|
||||
eText is the text field that can be dropped into and is editing the markdown.
|
||||
doMarkdown is the function returned by initLiveMarkdown.
|
||||
maxFileSize
|
||||
uploadUrl
|
||||
*/
|
||||
|
||||
function setupMarkdownUpload(eSubmit, eFileInput, eUploadBar, eText, doMarkdown, maxFileSize, uploadUrl) {
|
||||
const submitText = eSubmit.value;
|
||||
const uploadProgress = eUploadBar.querySelector('.progress');
|
||||
const uploadProgressText = eUploadBar.querySelector('.progress_text');
|
||||
const uploadProgressBar = eUploadBar.querySelector('.progress_bar');
|
||||
const uploadProgressBarFill = eUploadBar.querySelector('.progress_bar > div');
|
||||
let fileCounter = 0;
|
||||
let enterCounter = 0;
|
||||
let uploadQueue = [];
|
||||
let currentUpload = null;
|
||||
let currentXhr = null;
|
||||
let currentBatchSize = 0;
|
||||
let currentBatchDone = 0;
|
||||
|
||||
eFileInput.addEventListener("change", function(ev) {
|
||||
if (eFileInput.files.length > 0) {
|
||||
importUserFiles(eFileInput.files);
|
||||
}
|
||||
});
|
||||
|
||||
eText.addEventListener("dragover", function(ev) {
|
||||
let effect = "none";
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
|
||||
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
|
||||
effect = "copy";
|
||||
break;
|
||||
}
|
||||
}
|
||||
ev.dataTransfer.dropEffect = effect;
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
eText.addEventListener("dragenter", function(ev) {
|
||||
enterCounter++;
|
||||
let droppable = false;
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
|
||||
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
|
||||
droppable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (droppable) {
|
||||
eText.classList.add("drop");
|
||||
}
|
||||
});
|
||||
|
||||
eText.addEventListener("dragleave", function(ev) {
|
||||
enterCounter--;
|
||||
if (enterCounter == 0) {
|
||||
eText.classList.remove("drop");
|
||||
}
|
||||
});
|
||||
|
||||
function makeUploadString(uploadNumber, filename) {
|
||||
return `Uploading file #${uploadNumber}: \`${filename}\`...`;
|
||||
}
|
||||
|
||||
eText.addEventListener("drop", function(ev) {
|
||||
enterCounter = 0;
|
||||
eText.classList.remove("drop");
|
||||
|
||||
if (ev.dataTransfer && ev.dataTransfer.files) {
|
||||
importUserFiles(ev.dataTransfer.files)
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
eText.addEventListener("paste", function(ev) {
|
||||
const files = ev.clipboardData?.files ?? [];
|
||||
if (files.length > 0) {
|
||||
importUserFiles(files)
|
||||
}
|
||||
});
|
||||
|
||||
function importUserFiles(files) {
|
||||
let items = [];
|
||||
for (let i = 0; i < files.length; ++i) {
|
||||
let f = files[i];
|
||||
if (f.size < maxFileSize) {
|
||||
items.push({ file: f, error: null });
|
||||
} else {
|
||||
items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` });
|
||||
}
|
||||
}
|
||||
|
||||
let cursorStart = eText.selectionStart;
|
||||
let cursorEnd = eText.selectionEnd;
|
||||
|
||||
let toInsert = "";
|
||||
let linesToCursor = eText.value.substr(0, cursorStart).split("\n");
|
||||
let cursorLine = linesToCursor[linesToCursor.length-1].trim();
|
||||
if (cursorLine.length > 0) {
|
||||
toInsert = "\n\n";
|
||||
}
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
if (items[i].file) {
|
||||
fileCounter++;
|
||||
toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n\n";
|
||||
queueUpload(fileCounter, items[i].file);
|
||||
} else {
|
||||
toInsert += `${items[i].error}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
eText.value = eText.value.substring(0, cursorStart) + toInsert + eText.value.substring(cursorEnd, eText.value.length);
|
||||
doMarkdown();
|
||||
uploadNext();
|
||||
}
|
||||
|
||||
function replaceUploadString(upload, newString) {
|
||||
let cursorStart = eText.selectionStart;
|
||||
let cursorEnd = eText.selectionEnd;
|
||||
let uploadString = makeUploadString(upload.uploadNumber, upload.file.name);
|
||||
let insertIndex = eText.value.indexOf(uploadString)
|
||||
eText.value = eText.value.replace(uploadString, newString);
|
||||
if (cursorStart <= insertIndex + uploadString.length) {
|
||||
eText.selectionStart = cursorStart;
|
||||
} else {
|
||||
eText.selectionStart = cursorStart - uploadString.length + newString.length;
|
||||
}
|
||||
if (cursorEnd <= insertIndex + uploadString.length) {
|
||||
eText.selectionEnd = cursorEnd;
|
||||
} else {
|
||||
eText.selectionEnd = cursorEnd - uploadString.length + newString.length;
|
||||
}
|
||||
doMarkdown();
|
||||
}
|
||||
|
||||
function replaceUploadStringError(upload) {
|
||||
replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`);
|
||||
}
|
||||
|
||||
function queueUpload(uploadNumber, file) {
|
||||
uploadQueue.push({
|
||||
uploadNumber: uploadNumber,
|
||||
file: file
|
||||
});
|
||||
|
||||
currentBatchSize++;
|
||||
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
|
||||
}
|
||||
|
||||
function uploadDone(ev) {
|
||||
try {
|
||||
if (currentXhr.status == 200 && currentXhr.response) {
|
||||
if (currentXhr.response.url) {
|
||||
let url = currentXhr.response.url;
|
||||
let newString = `[${currentUpload.file.name}](${url})`;
|
||||
if (currentXhr.response.mime.startsWith("image")) {
|
||||
newString = "!" + newString;
|
||||
}
|
||||
|
||||
replaceUploadString(currentUpload, newString);
|
||||
} else if (currentXhr.response.error) {
|
||||
replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`);
|
||||
} else {
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
} else {
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
currentUpload = null;
|
||||
currentXhr = null;
|
||||
currentBatchDone++;
|
||||
uploadNext();
|
||||
}
|
||||
|
||||
function updateUploadProgress(ev) {
|
||||
if (ev.lengthComputable) {
|
||||
let progress = ev.loaded / ev.total;
|
||||
uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
function uploadNext() {
|
||||
if (currentUpload == null) {
|
||||
next = uploadQueue.shift();
|
||||
if (next) {
|
||||
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
|
||||
eUploadBar.classList.add("uploading");
|
||||
uploadProgressBarFill.style.width = "0%";
|
||||
eSubmit.disabled = true;
|
||||
eSubmit.value = "Uploading files...";
|
||||
|
||||
try {
|
||||
let utf8Filename = strToUTF8Arr(next.file.name);
|
||||
let base64Filename = base64EncArr(utf8Filename);
|
||||
// NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2
|
||||
currentXhr = new XMLHttpRequest();
|
||||
currentXhr.upload.addEventListener("progress", updateUploadProgress);
|
||||
currentXhr.open("POST", uploadUrl, true);
|
||||
currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename);
|
||||
currentXhr.responseType = "json";
|
||||
currentXhr.addEventListener("loadend", uploadDone);
|
||||
currentXhr.send(next.file);
|
||||
currentUpload = next;
|
||||
} catch (err) {
|
||||
replaceUploadStringError(next);
|
||||
console.error(err);
|
||||
uploadNext();
|
||||
}
|
||||
} else {
|
||||
eSubmit.disabled = false;
|
||||
eSubmit.value = submitText;
|
||||
eUploadBar.classList.remove("uploading");
|
||||
currentBatchSize = 0;
|
||||
currentBatchDone = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8512,6 +8512,7 @@ input[type=submit] {
|
|||
.avatar-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
border-radius: 100%;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<h2>Handmade Seattle</h2>
|
||||
</a>
|
||||
<div class="{{ $bannerclass }}" style="background-image: url('{{ static "hms/banner_tall.jpg" }}')"></div>
|
||||
<p>The spiritual successor to HandmadeCon, Handmade Seattle was started in 2019 by Abner Coimbre, the founder of Handmade Network. From the start, Handmade Seattle has been an independent conference, free from corporate sponsorships. The conferences are hybrid online/offline, so you can participate no matter where in the world you live.</p>
|
||||
<p>Handmade Seattle, the spiritual successor to HandmadeCon, was started in 2019 by Abner Coimbre, the founder of Handmade Network. From the start, Handmade Seattle has been an independent conference, free from corporate sponsorships. The conferences are hybrid online/physical, so you can participate no matter where in the world you live.</p>
|
||||
<p>Tickets can be purchased at <a href="https://handmade-seattle.com/">the conference website</a>.</p>
|
||||
<p><a href="https://media.handmade-seattle.com/tag/talks/">Talks</a> and <a href="https://media.handmade-seattle.com/tag/demos/">demos</a> can be viewed on the conference's media site.</p>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{{ template "markdown_previews.html" . }}
|
||||
|
||||
<script src="{{ static "js/base64.js" }}"></script>
|
||||
<script src="{{ static "js/markdown_upload.js" }}"></script>
|
||||
|
||||
<style>
|
||||
#editor {
|
||||
|
@ -121,222 +122,14 @@
|
|||
/*
|
||||
/ Asset upload
|
||||
*/
|
||||
const submitButton = document.querySelector("#form input[type=submit]");
|
||||
const submitText = submitButton.value;
|
||||
const fileInput = document.querySelector('#file_input');
|
||||
const uploadBar = document.querySelector('.upload_bar');
|
||||
const uploadProgress = document.querySelector('.upload_bar .progress');
|
||||
const uploadProgressText = document.querySelector('.upload_bar .progress_text');
|
||||
const uploadProgressBar = document.querySelector('.upload_bar .progress_bar');
|
||||
const uploadProgressBarFill = document.querySelector('.upload_bar .progress_bar > div');
|
||||
let fileCounter = 0;
|
||||
let enterCounter = 0;
|
||||
let uploadQueue = [];
|
||||
let currentUpload = null;
|
||||
let currentXhr = null;
|
||||
let currentBatchSize = 0;
|
||||
let currentBatchDone = 0;
|
||||
|
||||
fileInput.addEventListener("change", function(ev) {
|
||||
if (fileInput.files.length > 0) {
|
||||
importUserFiles(fileInput.files);
|
||||
}
|
||||
});
|
||||
|
||||
textField.addEventListener("dragover", function(ev) {
|
||||
let effect = "none";
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
|
||||
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
|
||||
effect = "copy";
|
||||
break;
|
||||
}
|
||||
}
|
||||
ev.dataTransfer.dropEffect = effect;
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
textField.addEventListener("dragenter", function(ev) {
|
||||
enterCounter++;
|
||||
let droppable = false;
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
|
||||
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
|
||||
droppable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (droppable) {
|
||||
textField.classList.add("drop");
|
||||
}
|
||||
});
|
||||
|
||||
textField.addEventListener("dragleave", function(ev) {
|
||||
enterCounter--;
|
||||
if (enterCounter == 0) {
|
||||
textField.classList.remove("drop");
|
||||
}
|
||||
});
|
||||
|
||||
function makeUploadString(uploadNumber, filename) {
|
||||
return `Uploading file #${uploadNumber}: \`${filename}\`...`;
|
||||
}
|
||||
|
||||
textField.addEventListener("drop", function(ev) {
|
||||
enterCounter = 0;
|
||||
textField.classList.remove("drop");
|
||||
|
||||
if (ev.dataTransfer && ev.dataTransfer.files) {
|
||||
importUserFiles(ev.dataTransfer.files)
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
textField.addEventListener("paste", function(ev) {
|
||||
const files = ev.clipboardData?.files ?? [];
|
||||
if (files.length > 0) {
|
||||
importUserFiles(files)
|
||||
}
|
||||
});
|
||||
|
||||
function importUserFiles(files) {
|
||||
let items = [];
|
||||
for (let i = 0; i < files.length; ++i) {
|
||||
let f = files[i];
|
||||
if (f.size < maxFileSize) {
|
||||
items.push({ file: f, error: null });
|
||||
} else {
|
||||
items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` });
|
||||
}
|
||||
}
|
||||
|
||||
let cursorStart = textField.selectionStart;
|
||||
let cursorEnd = textField.selectionEnd;
|
||||
|
||||
let toInsert = "";
|
||||
let linesToCursor = textField.value.substr(0, cursorStart).split("\n");
|
||||
let cursorLine = linesToCursor[linesToCursor.length-1].trim();
|
||||
if (cursorLine.length > 0) {
|
||||
toInsert = "\n\n";
|
||||
}
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
if (items[i].file) {
|
||||
fileCounter++;
|
||||
toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n\n";
|
||||
queueUpload(fileCounter, items[i].file);
|
||||
} else {
|
||||
toInsert += `${items[i].error}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
textField.value = textField.value.substring(0, cursorStart) + toInsert + textField.value.substring(cursorEnd, textField.value.length);
|
||||
doMarkdown();
|
||||
uploadNext();
|
||||
}
|
||||
|
||||
function replaceUploadString(upload, newString) {
|
||||
let cursorStart = textField.selectionStart;
|
||||
let cursorEnd = textField.selectionEnd;
|
||||
let uploadString = makeUploadString(upload.uploadNumber, upload.file.name);
|
||||
let insertIndex = textField.value.indexOf(uploadString)
|
||||
textField.value = textField.value.replace(uploadString, newString);
|
||||
if (cursorStart <= insertIndex + uploadString.length) {
|
||||
textField.selectionStart = cursorStart;
|
||||
} else {
|
||||
textField.selectionStart = cursorStart - uploadString.length + newString.length;
|
||||
}
|
||||
if (cursorEnd <= insertIndex + uploadString.length) {
|
||||
textField.selectionEnd = cursorEnd;
|
||||
} else {
|
||||
textField.selectionEnd = cursorEnd - uploadString.length + newString.length;
|
||||
}
|
||||
doMarkdown();
|
||||
}
|
||||
|
||||
function replaceUploadStringError(upload) {
|
||||
replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`);
|
||||
}
|
||||
|
||||
function queueUpload(uploadNumber, file) {
|
||||
uploadQueue.push({
|
||||
uploadNumber: uploadNumber,
|
||||
file: file
|
||||
});
|
||||
|
||||
currentBatchSize++;
|
||||
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
|
||||
}
|
||||
|
||||
function uploadDone(ev) {
|
||||
try {
|
||||
if (currentXhr.status == 200 && currentXhr.response) {
|
||||
if (currentXhr.response.url) {
|
||||
let url = currentXhr.response.url;
|
||||
let newString = `[${currentUpload.file.name}](${url})`;
|
||||
if (currentXhr.response.mime.startsWith("image")) {
|
||||
newString = "!" + newString;
|
||||
}
|
||||
|
||||
replaceUploadString(currentUpload, newString);
|
||||
} else if (currentXhr.response.error) {
|
||||
replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`);
|
||||
} else {
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
} else {
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
replaceUploadStringError(currentUpload);
|
||||
}
|
||||
currentUpload = null;
|
||||
currentXhr = null;
|
||||
currentBatchDone++;
|
||||
uploadNext();
|
||||
}
|
||||
|
||||
function updateUploadProgress(ev) {
|
||||
if (ev.lengthComputable) {
|
||||
let progress = ev.loaded / ev.total;
|
||||
uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
function uploadNext() {
|
||||
if (currentUpload == null) {
|
||||
next = uploadQueue.shift();
|
||||
if (next) {
|
||||
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
|
||||
uploadBar.classList.add("uploading");
|
||||
uploadProgressBarFill.style.width = "0%";
|
||||
submitButton.disabled = true;
|
||||
submitButton.value = "Uploading files...";
|
||||
|
||||
try {
|
||||
let utf8Filename = strToUTF8Arr(next.file.name);
|
||||
let base64Filename = base64EncArr(utf8Filename);
|
||||
// NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2
|
||||
currentXhr = new XMLHttpRequest();
|
||||
currentXhr.upload.addEventListener("progress", updateUploadProgress);
|
||||
currentXhr.open("POST", uploadUrl, true);
|
||||
currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename);
|
||||
currentXhr.responseType = "json";
|
||||
currentXhr.addEventListener("loadend", uploadDone);
|
||||
currentXhr.send(next.file);
|
||||
currentUpload = next;
|
||||
} catch (err) {
|
||||
replaceUploadStringError(next);
|
||||
console.error(err);
|
||||
uploadNext();
|
||||
}
|
||||
} else {
|
||||
submitButton.disabled = false;
|
||||
submitButton.value = submitText;
|
||||
uploadBar.classList.remove("uploading");
|
||||
currentBatchSize = 0;
|
||||
currentBatchDone = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
setupMarkdownUpload(
|
||||
document.querySelector("#form input[type=submit]"),
|
||||
document.querySelector('#file_input'),
|
||||
document.querySelector('.upload_bar'),
|
||||
textField,
|
||||
doMarkdown,
|
||||
maxFileSize,
|
||||
uploadUrl
|
||||
);
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
<script src="{{ static "js/tabs.js" }}"></script>
|
||||
<script src="{{ static "js/image_selector.js" }}"></script>
|
||||
<script src="{{ static "js/templates.js" }}"></script>
|
||||
<script src="{{ static "js/base64.js" }}"></script>
|
||||
<script src="{{ static "js/markdown_upload.js" }}"></script>
|
||||
|
||||
<style>
|
||||
#desc-preview:empty::after {
|
||||
|
@ -12,6 +14,10 @@
|
|||
color: var(--dimmer-color);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#description.drop {
|
||||
box-shadow: inset 0px 0px 5px yellow;
|
||||
}
|
||||
</style>
|
||||
{{ end }}
|
||||
|
||||
|
@ -156,6 +162,17 @@
|
|||
<textarea id="description" class="w-100 h5 minh-5 mono lh-copy" name="description">
|
||||
{{- .ProjectSettings.Description -}}
|
||||
</textarea>
|
||||
<div class="flex justify-end items-center mt2">
|
||||
<div class="upload_bar flex-grow-1">
|
||||
<div class="instructions">
|
||||
Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them.
|
||||
</div>
|
||||
<div class="progress flex">
|
||||
<div class="progress_text mr3"></div>
|
||||
<div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="b mt3 mb2">Preview:</div>
|
||||
<div id="desc-preview" class="w-100"></div>
|
||||
</div>
|
||||
|
@ -196,6 +213,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<input type="file" multiple name="file_input" id="file_input" class="dn" />{{/* NOTE(mark): copied NOTE(asaf): Placing this outside the form to avoid submitting it to the server by accident */}}
|
||||
</div>
|
||||
<script>
|
||||
let csrf = JSON.parse({{ csrftokenjs .Session }});
|
||||
|
@ -366,6 +384,19 @@
|
|||
logoMaxFileSize,
|
||||
document.querySelector(".dark_logo")
|
||||
);
|
||||
|
||||
|
||||
//////////////////
|
||||
// Asset upload //
|
||||
//////////////////
|
||||
setupMarkdownUpload(
|
||||
document.querySelector("#project_form [data-name=Description] input[type=submit]"),
|
||||
document.querySelector('#file_input'),
|
||||
document.querySelector('.upload_bar'),
|
||||
description,
|
||||
doMarkdown,
|
||||
{{ .MaxFileSize }},
|
||||
{{ .UploadUrl }}
|
||||
);
|
||||
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
.admin .cover {
|
||||
background: repeating-linear-gradient( -45deg, #ff6c00, #ff6c00 12px, #000000 5px, #000000 25px );
|
||||
}
|
||||
|
||||
</style>
|
||||
{{ end }}
|
||||
|
||||
|
|
|
@ -402,6 +402,9 @@ type ProjectEditData struct {
|
|||
|
||||
APICheckUsernameUrl string
|
||||
LogoMaxFileSize int
|
||||
|
||||
MaxFileSize int
|
||||
UploadUrl string
|
||||
}
|
||||
|
||||
func ProjectNew(c *RequestContext) ResponseData {
|
||||
|
@ -428,6 +431,9 @@ func ProjectNew(c *RequestContext) ResponseData {
|
|||
|
||||
APICheckUsernameUrl: hmnurl.BuildAPICheckUsername(),
|
||||
LogoMaxFileSize: ProjectLogoMaxFileSize,
|
||||
|
||||
MaxFileSize: AssetMaxSize(c.CurrentUser),
|
||||
UploadUrl: c.UrlContext.BuildAssetUpload(),
|
||||
}, c.Perf)
|
||||
return res
|
||||
}
|
||||
|
@ -552,6 +558,9 @@ func ProjectEdit(c *RequestContext) ResponseData {
|
|||
|
||||
APICheckUsernameUrl: hmnurl.BuildAPICheckUsername(),
|
||||
LogoMaxFileSize: ProjectLogoMaxFileSize,
|
||||
|
||||
MaxFileSize: AssetMaxSize(c.CurrentUser),
|
||||
UploadUrl: c.UrlContext.BuildAssetUpload(),
|
||||
}, c.Perf)
|
||||
return res
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue