155 lines
4.5 KiB
Plaintext
155 lines
4.5 KiB
Plaintext
package views
|
|
|
|
import "thamanyah/cms/v2/internal/views/layouts"
|
|
|
|
templ VideoUpload(categories []string) {
|
|
@layouts.Layout("Upload Video · Thamanyah CMS") {
|
|
<h1>Upload a video</h1>
|
|
<p>Provide the video file along with its metadata.</p>
|
|
<form id="upload-form">
|
|
<div class="field">
|
|
<label for="title">Title</label>
|
|
<input type="text" id="title" name="title" required/>
|
|
</div>
|
|
<div class="field">
|
|
<label for="description">Description</label>
|
|
<textarea id="description" name="description" rows="4"></textarea>
|
|
</div>
|
|
<div class="field">
|
|
<label for="category">Categories</label>
|
|
<select id="category" name="category" multiple>
|
|
for _, category := range categories {
|
|
<option value={ category }>{ category }</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
<div class="field">
|
|
<label for="tags">Tags</label>
|
|
<input type="text" id="tags" name="tags" placeholder="comma, separated, tags"/>
|
|
</div>
|
|
<div class="field">
|
|
<label for="video">Video file</label>
|
|
<input type="file" id="video" name="video" accept="video/*" required/>
|
|
</div>
|
|
<progress id="upload-progress" value="0" max="100"></progress>
|
|
<button type="submit">Upload</button>
|
|
</form>
|
|
<div id="upload-result"></div>
|
|
<script>
|
|
document.getElementById('upload-form').addEventListener('submit', function (evt) {
|
|
evt.preventDefault();
|
|
|
|
var form = evt.target;
|
|
var fileInput = document.getElementById('video');
|
|
var file = fileInput.files[0];
|
|
var resultEl = document.getElementById('upload-result');
|
|
var progressEl = document.getElementById('upload-progress');
|
|
var button = form.querySelector('button[type="submit"]');
|
|
|
|
function showError(message) {
|
|
resultEl.innerHTML = '<div class="result result-error"><p>' + message + '</p></div>';
|
|
}
|
|
|
|
if (!file) {
|
|
showError('A video file is required.');
|
|
return;
|
|
}
|
|
|
|
var contentType = file.type || 'application/octet-stream';
|
|
|
|
button.disabled = true;
|
|
progressEl.value = 0;
|
|
resultEl.innerHTML = '';
|
|
|
|
fetch('/videos/presign', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ fileName: file.name, contentType: contentType })
|
|
}).then(function (res) {
|
|
return res.json().then(function (body) {
|
|
if (!res.ok) {
|
|
throw new Error(body.error || 'Could not prepare upload.');
|
|
}
|
|
return body;
|
|
});
|
|
}).then(function (presigned) {
|
|
return new Promise(function (resolve, reject) {
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('PUT', presigned.uploadUrl);
|
|
xhr.setRequestHeader('Content-Type', contentType);
|
|
xhr.upload.addEventListener('progress', function (e) {
|
|
if (e.lengthComputable) {
|
|
progressEl.value = Math.round((e.loaded / e.total) * 100);
|
|
}
|
|
});
|
|
xhr.onload = function () {
|
|
if (xhr.status >= 200 && xhr.status < 300) {
|
|
resolve(presigned.key);
|
|
} else {
|
|
reject(new Error('Upload to storage failed.'));
|
|
}
|
|
};
|
|
xhr.onerror = function () {
|
|
reject(new Error('Upload to storage failed.'));
|
|
};
|
|
xhr.send(file);
|
|
});
|
|
}).then(function (key) {
|
|
return fetch('/videos', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
title: form.title.value.trim(),
|
|
description: form.description.value.trim(),
|
|
categories: Array.prototype.map.call(form.category.selectedOptions, function (o) { return o.value; }),
|
|
tags: form.tags.value.trim(),
|
|
fileName: file.name,
|
|
key: key
|
|
})
|
|
});
|
|
}).then(function (res) {
|
|
return res.text().then(function (html) {
|
|
resultEl.innerHTML = html;
|
|
});
|
|
}).catch(function (err) {
|
|
showError(err.message);
|
|
}).finally(function () {
|
|
button.disabled = false;
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
}
|
|
|
|
templ VideoUploadSuccess(v VideoMetadata) {
|
|
<div class="result result-success">
|
|
<h2>Upload complete</h2>
|
|
<dl>
|
|
<dt>Title</dt>
|
|
<dd>{ v.Title }</dd>
|
|
if v.Description != "" {
|
|
<dt>Description</dt>
|
|
<dd>{ v.Description }</dd>
|
|
}
|
|
<dt>Categories</dt>
|
|
<dd>{ joinCategories(v.Categories) }</dd>
|
|
<dt>Enqueue Job ID</dt>
|
|
<dd>{ v.JobID }</dd>
|
|
if v.Tags != "" {
|
|
<dt>Tags</dt>
|
|
<dd>{ v.Tags }</dd>
|
|
}
|
|
<dt>File</dt>
|
|
<dd>
|
|
{ v.FileName } ({ formatSize(v.SizeBytes) })
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
}
|
|
|
|
templ VideoUploadError(message string) {
|
|
<div class="result result-error">
|
|
<p style="color:green">{ message }</p>
|
|
</div>
|
|
}
|