Skip to content

Commit

Permalink
Add file model and display uploaded files
Browse files Browse the repository at this point in the history
  • Loading branch information
audiodude committed Nov 14, 2023
1 parent 7d3c4a2 commit 5c7e48d
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 13 deletions.
11 changes: 9 additions & 2 deletions rainfall-frontend/src/components/ReleasesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ export default {
<template>
<div>
<div v-if="releases.length > 0" class="md:max-w-screen-md mt-8 p-4 border border-emerald-500">
<div v-for="release in releases" class="mb-2 last:mb-0">
<div v-for="release in releases" class="mb-6 last:mb-0">
<div class="flex flex-row justify-between p-2 bg-emerald-500 text-white">
<span class="release-name">
{{ release.name }}
</span>
</div>
<div v-for="file of release.files" class="text-right my-2">
{{ file.filename }}
</div>
<div v-if="release.files.length == 0" class="text-right mt-4">
<span class="italic">No files uploaded yet</span>
</div>
<hr class="my-4" />
<div class="text-right">
<SongUpload :releaseId="release.id" class="ml-10" />
<SongUpload :releaseId="release.id" class="md:ml-40" />
</div>
</div>
</div>
Expand Down
27 changes: 24 additions & 3 deletions rainfall-frontend/src/components/SongUpload.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
<script lang="ts">
export default {
props: ['releaseId'],
data(): { files: FileList | null } {
data(): { files: FileList | null; fileError: string | null } {
return {
files: null,
fileError: null,
};
},
methods: {
upload() {
async upload() {
if (!this.files) {
return;
}
this.fileError = null;
let formData = new FormData();
for (const song of this.files) {
formData.append('song[]', song);
}
formData.append('release_id', this.releaseId);
fetch('/api/v1/upload', { method: 'POST', credentials: 'include', body: formData });
const resp = await fetch('/api/v1/upload', {
method: 'POST',
credentials: 'include',
body: formData,
});
if (resp.ok) {
return;
}
let error = 'An unknown error occurred';
if (resp.headers.get('Content-Type') == 'application/json') {
const data = await resp.json();
error = data.error;
}
setTimeout(() => {
this.fileError = error;
}, 250);
},
fileChanged() {
this.files = this.fileInput.files ? this.fileInput.files : null;
Expand Down Expand Up @@ -50,6 +70,7 @@ export default {
Upload Songs
</button></label
>
<span v-if="fileError" class="text-red-600 dark:text-red-400">{{ fileError }}</span>
</div>
</template>

Expand Down
6 changes: 4 additions & 2 deletions rainfall-frontend/src/views/WelcomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ export default {
Keep in mind: Rainfall will <em>not</em> be hosting your site! Rainfall only exists to help
you gather your materials and metadata and generate your music website.
</p>
<div class="flex mt-8">
<input v-model="ready" name="agree" type="checkbox" class="block max-w-sm" />
<div class="flex flex-row mt-8">
<div class="flex flex-col justify-center">
<input v-model="ready" name="agree" type="checkbox" class="block max-w-sm" />
</div>
<div class="ml-4 max-w-2xl">
<label for="agree" class="text-lg">
I understand that Rainfall will not make my songs or site available to the outside
Expand Down
5 changes: 5 additions & 0 deletions rainfall/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from rainfall.db import db
from rainfall.login import check_csrf, save_or_update_google_user
from rainfall.models.file import File
from rainfall.models.release import Release
from rainfall.models.site import Site
from rainfall.models.user import User
Expand Down Expand Up @@ -207,8 +208,12 @@ def upload(user):
os.makedirs(release_path, exist_ok=True)
for song in song_files:
name = secure_filename(song.filename)
release.files.append(File(filename=name))
song.save(os.path.join(release_path, name))

db.session.add(release)
db.session.commit()

return '', 204

return app
27 changes: 27 additions & 0 deletions rainfall/models/file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from dataclasses import dataclass, fields
from functools import partial

from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.types import Uuid, String
from uuid_extensions import uuid7

from rainfall.db import db


@dataclass
class File(db.Model):
__tablename__ = 'files'

id: Mapped[bytes] = mapped_column(Uuid, primary_key=True, default=uuid7)
release_id: Mapped[bytes] = mapped_column(ForeignKey("releases.id"))
release: Mapped["Release"] = relationship(back_populates="files")
filename: Mapped[str] = mapped_column(String(1024))

def __repr__(self) -> str:
return f'File(id={self.id!r}, release_id={self.release_id!r})'

def serialize(self):
return dict((field.name, getattr(self, field.name))
for field in fields(self)
if field.name != 'release')
19 changes: 15 additions & 4 deletions rainfall/models/release.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import List
from dataclasses import dataclass, fields
from functools import partial

Expand All @@ -18,10 +19,20 @@ class Release(db.Model):
site: Mapped["Site"] = relationship(back_populates="releases")
name: Mapped[str] = mapped_column(String(255))

files: Mapped[List["File"]] = relationship(back_populates="release")

def __repr__(self) -> str:
return f'Release(id={self.id!r}, site_id={self.site!r})'
return f'Release(id={self.id!r}, site_id={self.site_id!r})'

def serialize(self):
return dict((field.name, getattr(self, field.name))
for field in fields(self)
if field.name != 'site')
props = []
for field in fields(self):
if field.name == 'site':
continue

if field.name == 'files':
props.append(('files', [file.serialize() for file in self.files]))
continue

props.append((field.name, getattr(self, field.name)))
return dict(props)
3 changes: 1 addition & 2 deletions rainfall/models/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ def serialize(self):

if field.name == 'releases':
props.append(
('releases',
[release.serialize() for release in getattr(self, 'releases')]))
('releases', [release.serialize() for release in self.releases]))
continue

props.append((field.name, getattr(self, field.name)))
Expand Down

0 comments on commit 5c7e48d

Please sign in to comment.