Quasi finito
parent
0c2009b659
commit
bd0a9b5c6e
@ -0,0 +1,106 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||||
|
import { Icon } from '../components/Icon.jsx'
|
||||||
|
import { useStore } from '../context.jsx'
|
||||||
|
import { useRemoteState } from '../util.jsx'
|
||||||
|
|
||||||
|
export const Bucket = () => {
|
||||||
|
const {
|
||||||
|
route: {
|
||||||
|
params: { bucket },
|
||||||
|
},
|
||||||
|
showToast,
|
||||||
|
} = useStore()
|
||||||
|
|
||||||
|
const [bucketObjects, updateBucketObjects] = useRemoteState(`/api/buckets/${bucket}`, [])
|
||||||
|
|
||||||
|
const fileInputRef = useRef(null)
|
||||||
|
|
||||||
|
const uploadFile = async () => {
|
||||||
|
const formData = new FormData()
|
||||||
|
|
||||||
|
formData.append('file', fileInputRef.current.files[0])
|
||||||
|
|
||||||
|
showToast(<>Sto caricando il file...</>)
|
||||||
|
|
||||||
|
const res = await fetch(`/api/buckets/${bucket}`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
const { id } = await res.json()
|
||||||
|
|
||||||
|
showToast(
|
||||||
|
<>
|
||||||
|
File caricato con id <code>{id}</code>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
await updateBucketObjects()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteObject = async id => {
|
||||||
|
const res = await fetch(`/api/buckets/${bucket}/${id}`, { method: 'DELETE' })
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
showToast('Oggetto rimosso')
|
||||||
|
} else {
|
||||||
|
showToast(`Errore: ${await res.text()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div class="panel">
|
||||||
|
<div class="row">
|
||||||
|
<div class="row-group">
|
||||||
|
<div class="title">
|
||||||
|
Bucket / <code>{bucket}</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row-group">
|
||||||
|
<button class="icon" onClick={() => fileInputRef.current.click()}>
|
||||||
|
<Icon name="file_upload" />
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref={fileInputRef}
|
||||||
|
onChange={() => uploadFile()}
|
||||||
|
style="display: none;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<div class="cells">
|
||||||
|
{/* Header */}
|
||||||
|
<div class="header">Objects</div>
|
||||||
|
<div class="header">Actions</div>
|
||||||
|
{/* Rows */}
|
||||||
|
{bucketObjects.map(key => (
|
||||||
|
<>
|
||||||
|
<div class="name">
|
||||||
|
<code>{key}</code>
|
||||||
|
</div>
|
||||||
|
<div class="options">
|
||||||
|
<a
|
||||||
|
class="button icon flat"
|
||||||
|
href={`/api/buckets/${bucket}/${key}`}
|
||||||
|
>
|
||||||
|
<Icon name="file_download" />
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
class="icon delete flat"
|
||||||
|
onClick={() => deleteObject(key)}
|
||||||
|
>
|
||||||
|
<Icon name="delete" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
import { useEffect, useState } from 'preact/hooks'
|
||||||
|
import { Icon } from '../components/Icon.jsx'
|
||||||
|
import { showToast } from '../components/Toasts.jsx'
|
||||||
|
import { useRemoteState } from '../util.jsx'
|
||||||
|
|
||||||
|
export const Buckets = () => {
|
||||||
|
const [buckets, updateBuckets] = useRemoteState('/api/buckets', [])
|
||||||
|
const [allBucketSettings, setAllBucketSettings] = useState({})
|
||||||
|
|
||||||
|
const updateBucketSettings = async bucket => {
|
||||||
|
const res = await fetch(`/api/buckets/${bucket}/settings`)
|
||||||
|
const value = await res.json()
|
||||||
|
|
||||||
|
setAllBucketSettings(s => ({ ...s, [bucket]: value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
for (const bucket of buckets) {
|
||||||
|
updateBucketSettings(bucket)
|
||||||
|
}
|
||||||
|
}, [buckets])
|
||||||
|
|
||||||
|
const [newBucketName, setNewBucketName] = useState('')
|
||||||
|
const [newBucketSettings, setNewBucketSettings] = useState('')
|
||||||
|
|
||||||
|
const createBucket = async () => {
|
||||||
|
const { path } = JSON.parse(newBucketSettings || '{"path":""}')
|
||||||
|
|
||||||
|
const res = await fetch(`/api/buckets/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
bucket: newBucketName,
|
||||||
|
path,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
await updateBuckets()
|
||||||
|
} else {
|
||||||
|
showToast(`Errore: ${await res.text()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div class="panel">
|
||||||
|
<div class="row">
|
||||||
|
<div class="row-group">
|
||||||
|
<div class="title">Buckets</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<div class="cells">
|
||||||
|
{/* Header */}
|
||||||
|
<div class="header">Bucket</div>
|
||||||
|
<div class="header">Settings</div>
|
||||||
|
<div class="header">Options</div>
|
||||||
|
{/* Rows */}
|
||||||
|
{buckets.map(bucket => (
|
||||||
|
<>
|
||||||
|
<div class="name">
|
||||||
|
<a href={`/buckets/${bucket}`}>
|
||||||
|
<code>{bucket}</code>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="settings">
|
||||||
|
<input
|
||||||
|
readonly
|
||||||
|
class="mono"
|
||||||
|
type="text"
|
||||||
|
value={JSON.stringify(allBucketSettings[bucket])}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="options">
|
||||||
|
<button class="icon delete flat">
|
||||||
|
<Icon name="delete" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="/api/buckets" method="POST">
|
||||||
|
<div class="fill title">Nuovo Bucket</div>
|
||||||
|
|
||||||
|
<label for="new-bucket-name">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="bucket"
|
||||||
|
id="new-bucket-name"
|
||||||
|
placeholder="new-bucket"
|
||||||
|
value={newBucketName}
|
||||||
|
onInput={e => setNewBucketName(e.target.value)}
|
||||||
|
/>
|
||||||
|
<label for="new-bucket-settings">Settings</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="settings"
|
||||||
|
id="new-bucket-settings"
|
||||||
|
placeholder={`{"path":"${newBucketName || 'new-bucket'}/"}`}
|
||||||
|
value={newBucketSettings}
|
||||||
|
onInput={e => setNewBucketSettings(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="fill center">
|
||||||
|
<button type="button" onClick={() => createBucket()}>
|
||||||
|
Crea Bucket
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue