1
0
Fork 0

Initial create dialogue, switch to tailwindcss

upload-progress
Ambrose Chua 2021-05-23 15:36:41 +08:00
parent 7a2bea5969
commit 4a3c93dbbb
15 changed files with 1443 additions and 100 deletions

View File

@ -1,5 +1,7 @@
FROM node:16-alpine3.13 as build-web
ARG NODE_ENV=production
WORKDIR /src
COPY . .
RUN cd web && npm install

View File

@ -2,7 +2,17 @@ package main
import (
"embed"
"io/fs"
)
//go:embed web/*.tmpl web/assets/*
var assets embed.FS
var assetsWeb = fsMust(fs.Sub(assets, "web"))
func fsMust(fs fs.FS, err error) fs.FS {
if err != nil {
panic(err)
}
return fs
}

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"html/template"
"io"
"net/http"
"os"
"time"
@ -12,6 +13,7 @@ import (
)
var globalStore store
var handleAssets = http.FileServer(http.FS(assetsWeb))
func setupHandlers() {
var err error
@ -19,6 +21,10 @@ func setupHandlers() {
if err != nil {
panic(err)
}
if debug {
handleAssets = http.FileServer(http.FS(os.DirFS("web/assets/")))
}
}
/* credentials */
@ -57,6 +63,13 @@ func setCredential(id string, cred credential, expire time.Duration) error {
var tmpl = template.Must(template.ParseFS(assets, "web/*.tmpl"))
func executeTemplate(w io.Writer, name string, data interface{}) error {
if debug {
tmpl = template.Must(template.ParseGlob("web/*.tmpl"))
}
return tmpl.ExecuteTemplate(w, name, nil)
}
/* upload template */
func handleUpload(w http.ResponseWriter, req *http.Request) {
@ -64,7 +77,7 @@ func handleUpload(w http.ResponseWriter, req *http.Request) {
_, err := getCredential(vars["id"])
if errors.Is(err, errNotFound) {
errorResponseStatus(w, req, err)
tmpl.ExecuteTemplate(w, "upload-not-found.tmpl", nil)
executeTemplate(w, "upload-not-found.tmpl", nil)
return
}
if err != nil {
@ -72,11 +85,11 @@ func handleUpload(w http.ResponseWriter, req *http.Request) {
return
}
tmpl.ExecuteTemplate(w, "upload.tmpl", nil)
executeTemplate(w, "upload.tmpl", nil)
}
/* create template */
func handleCreate(w http.ResponseWriter, req *http.Request) {
tmpl.ExecuteTemplate(w, "create.tmpl", nil)
executeTemplate(w, "create.tmpl", nil)
}

17
main.go
View File

@ -1,7 +1,6 @@
package main
import (
"io/fs"
"log"
"net/http"
"os"
@ -10,17 +9,14 @@ import (
"github.com/gorilla/mux"
)
var debug = os.Getenv("DEBUG") == "true"
func main() {
listen := os.Getenv("LISTEN")
if listen == "" {
listen = ":8080"
}
assetsWeb, err := fs.Sub(assets, "web")
if err != nil {
panic(err)
}
setupHandlers()
setupS3()
@ -28,8 +24,9 @@ func main() {
router.Use(middlewareLogger)
router.Methods(http.MethodGet).Path("/readyz").HandlerFunc(readyz)
router.Methods(http.MethodGet).PathPrefix("/assets").Handler(http.FileServer(http.FS(assetsWeb)))
router.Methods(http.MethodGet).Path("/").HandlerFunc(handleCreate)
router.Methods(http.MethodGet).PathPrefix("/assets").Handler(handleAssets)
router.Methods(http.MethodGet).Path("/create").HandlerFunc(handleCreate)
uploadRouter := router.PathPrefix("/{id}").Subrouter()
uploadTemplateRouter := uploadRouter.Path("").Subrouter()
@ -49,8 +46,8 @@ func main() {
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
log.Printf("listeining on %s", listen)
err = server.ListenAndServe()
log.Printf("listening on %s", listen)
err := server.ListenAndServe()
if err != nil {
panic(err)
}

116
web/create.tmpl Normal file
View File

@ -0,0 +1,116 @@
{{template "head.tmpl" "Create Dropbox"}}
<form class="space-y-6">
<section class="space-y-4">
<div class="flex items-center">
<h4 class="my-2 flex-1 text-lg font-bold">Bucket options</h4>
<span>
<input
class="rounded"
type="checkbox"
id="options-save-bucket"
data-save="Endpoint,Region,AccessKey,SecretKey,Prefix,ACL">
<label for="options-save-bucket">Remember</label>
</span>
</div>
<div>
<label for="options-endpoint">Endpoint</label>
<div class="mt-1">
<input
class="w-full rounded-md border-gray-400"
type="url"
id="options-endpoint"
name="Endpoint"
placeholder="https://bucketname.s3.us-west-2.amazonaws.com">
</div>
</div>
<div>
<label for="options-region">Region</label>
<div class="mt-1">
<input
class="w-full rounded-md border-gray-400"
type="text"
id="options-region"
name="Region"
placeholder="us-west-2">
</div>
</div>
<div>
<label for="options-accesskey">Access key</label>
<div class="mt-1">
<input
class="w-full rounded-md border-gray-400"
type="text"
id="options-accesskey"
name="AccessKey"
placeholder="">
</div>
</div>
<div>
<label for="options-secretkey">Secret key</label>
<div class="mt-1">
<input
class="w-full rounded-md border-gray-400"
type="text"
id="options-secretkey"
name="SecretKey"
placeholder="">
</div>
</div>
</section>
<section class="space-y-4">
<div class="flex items-center">
<h4 class="my-2 flex-1 text-lg font-bold">Upload options</h4>
<span>
<input
class="rounded"
type="checkbox"
id="options-save-upload"
data-save="Prefix,ExpiryNumber,ExpiryUnits">
<label for="options-save-upload">Remember</label>
</span>
</div>
<div>
<label for="options-prefix">Prefix</label>
<div class="mt-1">
<input
class="w-full rounded-md border-gray-400"
type="text"
id="options-prefix"
name="Prefix"
placeholder="uploads/"
value="{random}/">
</div>
<p class="mt-1 text-sm text-gray-500">
Files will be uploaded with this prefix. For a random 16-character <code>[a-z0-9]</code> prefix , use <code>{random}</code>.
</p>
</div>
<div>
<label for="options-expiry-number">Expiry</label>
<div class="mt-1 flex">
<input
class="w-full rounded-l-md border-gray-400"
type="number"
id="options-expiry-number"
name="ExpiryNumber"
value="7"
min="0">
<select
class="rounded-r-md border-gray-400"
id="options-expiry-unit"
name="ExpiryUnits">
<option value="m">minutes</option>
<option value="h">hours</option>
<option value="d" selected>days</option>
</select>
</div>
<p class="mt-1 text-sm text-gray-500">
Time until the link expires, and credentials are purged from the server.
</p>
<input type="hidden" name="Expiry" value="" data-derive="duration,ExpiryNumber,ExpiryUnits">
</div>
</section>
</form>
{{template "foot.tmpl"}}

View File

@ -1,3 +1,4 @@
</main>
</body>
</html>

View File

@ -8,3 +8,9 @@
<link rel="stylesheet" href="assets/bundle.css">
</head>
<body>
<noscript>
<p class="p-6 bg-red-100 text-red-700">
This tool requires JavaScript to be enabled in your browser.
</p>
</noscript>
<main class="w-full max-w-3xl mx-auto">

1252
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
"devDependencies": {
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@tailwindcss/forms": "^0.3.2",
"@uppy/aws-s3-multipart": "^1.8.15",
"@uppy/core": "^1.18.1",
"@uppy/drag-drop": "^1.4.27",
@ -18,6 +19,7 @@
"rollup": "^2.48.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-terser": "^7.0.2"
"rollup-plugin-terser": "^7.0.2",
"tailwindcss": "^2.1.2"
}
}

View File

@ -15,10 +15,20 @@ export default {
},
plugins: [
commonjs(),
resolve({ browser: true }),
postcss({ extract: true, minimize: true }),
copy({ targets: [
{ src: 'static/favicon.png', dest: 'assets' },
] }),
resolve({
browser: true,
}),
postcss({
plugins: [
require('tailwindcss'),
],
extract: true,
minimize: true,
}),
copy({
targets: [
{ src: 'static/favicon.png', dest: 'assets' },
],
}),
],
};

View File

@ -1,27 +0,0 @@
.log-item {
display: flex;
align-items: center;
margin: 0.5rem 0;
border: 2px solid #adadad;
border-radius: 7px;
}
.log-url {
padding: 0.5rem;
flex: 1;
width: 10rem;
appearance: none;
outline: none;
border: none;
background: none;
}
.log-size {
padding: 0.25rem 0.5rem;
white-space: nowrap;
font-weight: 600;
font-size: 0.8em;
}

View File

@ -1,7 +1,5 @@
import filesize from 'filesize';
import './log.css';
class Log {
constructor(selector, key) {
this.key = key;

View File

@ -1,38 +0,0 @@
*, *:before, *:after {
box-sizing: border-box;
}
html {
height: 100%;
}
html, input {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
body {
height: 100%;
margin: 0;
}
.upload-wrapper {
max-width: 48rem;
width: 100%;
margin: 0 auto;
}
.upload {
padding: 2rem;
}
#log-header {
margin-top: 2rem;
display: flex;
}
#log-header h4 {
flex: 1;
margin: 0.5rem 0;
}

View File

@ -3,13 +3,25 @@ import DragDrop from '@uppy/drag-drop';
import StatusBar from '@uppy/status-bar';
import AwsS3Multipart from '@uppy/aws-s3-multipart';
/* CSS */
import 'tailwindcss/tailwind.css';
import '@uppy/core/dist/style.css';
import '@uppy/drag-drop/dist/style.css';
import '@uppy/status-bar/dist/style.css';
import './main.css';
/* Components */
import Log from './log';
const log = new Log('#log-area', window.location.pathname);
document.querySelector('#log-clear').addEventListener('click', () => {
log.clear();
});
/* Uppy */
const uppy = new Uppy({
autoProceed: true,
});
@ -25,7 +37,7 @@ uppy.use(AwsS3Multipart, {
companionUrl: window.location.pathname,
});
const log = new Log('#log-area', window.location.pathname);
/* Uppy handlers */
uppy.on('upload-success', (f, res) => {
log.add({
@ -34,7 +46,3 @@ uppy.on('upload-success', (f, res) => {
location: res.body.Location,
});
});
document.querySelector('#log-clear').addEventListener('click', () => {
log.clear();
});

9
web/tailwind.config.js Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
purge: [
'./*.tmpl',
'./src/*.js',
],
plugins: [
require('@tailwindcss/forms'),
],
};