Skip to content

Commit

Permalink
playlists create form (rauversion#15)
Browse files Browse the repository at this point in the history
* playlists form

* playlist create and profile playlist view

* playlist show

* modal on the playlist

* user suggestions

* track component optimize query with likes & reposts

* playlist likes + on_delete callbacks

* playlist likes view implementation

* move share track modal to its own component

* share playlist btn/modal

* move playlist load to the playlist list component

* ga fix migrations

* infinite scroll on playlists

* remove handler on playlist list

* edit playlist modal

* edit playlist form

* upload playlist cover

* ci test

* track live show
  • Loading branch information
michelson authored Jul 9, 2022
1 parent 9bcd835 commit 77068e7
Show file tree
Hide file tree
Showing 57 changed files with 2,238 additions and 336 deletions.
18 changes: 8 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,11 @@ jobs:
MIX_ENV: test
steps:
- uses: actions/checkout@v2
#- uses: mfinelli/setup-imagemagick@v1
#- name: Install Ubuntu dependencies
# run: sudo apt-get -y install poppler-data poppler-utils ffmpeg mupdf-tools
- name: installs audiowaveform
uses: actions/cache@v1
id: build-cache
run: sudo add-apt-repository ppa:chris-needham/ppa
run: sudo apt-get update
run: sudo apt-get install audiowaveform
- uses: mfinelli/setup-imagemagick@v1
- uses: FedericoCarboni/setup-ffmpeg@v1

- name: installs lame
run: sudo apt-get update -y; sudo apt-get install -y lame

- name: Check identify
run: identify --version
Expand All @@ -41,4 +37,6 @@ jobs:
otp-version: '24'
elixir-version: '1.12'
- run: mix deps.get
- run: mix test
- run: mix ecto.create ; mix ecto.migrate
# for now we will run only backend tests
- run: mix test test/rauversion
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
## images

### TODO

- [x] User account
- [x] File uploads Avatar
- [x] User auth
- [x] Tracks
- [x] Add metadata form step
- [x] Embed at /embed/:track_id
- [x] Embed at /embed/:track_id/private with signed_id
- [ ] make GithubActions work!
- [ ] Paginate profile tracks /:username
- [ ] Paginate /tracks
- [ ] Listening history
Expand All @@ -48,7 +48,6 @@ Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
- [x] Followers / Followings
- [ ] Telemetry for dashboard
- [ ] Centralized player, fixed (bottom) across navigation

- [x] load waveform data as data
- [x] Range responses

Expand Down
13 changes: 13 additions & 0 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { Application } from "@hotwired/stimulus"

import "./controllers"

import InfiniteScroll from "./hooks/infinite_scroll"

import WaveSurfer from 'wavesurfer'

// import * as ActiveStorage from "@rails/activestorage"
Expand Down Expand Up @@ -110,6 +112,17 @@ Hooks.AudioPlayer = {
},
}

Hooks.InfiniteScroll = InfiniteScroll


// handler for remove playlist, this is basically because we are using pxh-update=append on the playlist list
window.addEventListener(`phx:remove-playlist`, (e) => {
let el = document.getElementById(e.detail.id)
if(el) {
el.remove()
}
})

let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, params: {_csrf_token: csrfToken}})

// connect if there are any LiveViews on the page
Expand Down
29 changes: 29 additions & 0 deletions assets/js/hooks/infinite_scroll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// taken from: https://elixircasts.io/infinite-scroll-with-liveview

let scrollAt = () => {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
let scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight
let clientHeight = document.documentElement.clientHeight

return scrollTop / (scrollHeight - clientHeight) * 100
}

InfiniteScroll = {
page() { return this.el.dataset.page },
mounted(){
this.pending = this.page()

const target = this.el.dataset.phxComponent
window.addEventListener("scroll", e => {
if(this.pending == this.page() && scrollAt() > 90){
console.log(this.el.dataset.paginateEnd)
this.pending = this.page()
this.pushEventTo(target, "paginate", {})
}
})
},
reconnected(){ this.pending = this.page() },
updated(){ this.pending = this.page() }
}

export default InfiniteScroll
6 changes: 6 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ config :rauversion, Rauversion.Repo,
ownership_timeout: 300_000_000,
timeout: 300_000_000

if System.get_env("GITHUB_ACTIONS") do
config :rauversion, Chaskiq.Repo,
username: "postgres",
password: "postgres"
end

# We don't run a server during test. If one is required,
# you can enable the server option below.
config :rauversion, RauversionWeb.Endpoint,
Expand Down
18 changes: 15 additions & 3 deletions lib/rauversion/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,21 @@ defmodule Rauversion.Accounts.User do
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime

has_many :tracks, Rauversion.Tracks.Track
has_many :followings, Rauversion.UserFollows.UserFollow, foreign_key: :following_id
has_many :followers, Rauversion.UserFollows.UserFollow, foreign_key: :follower_id
has_many :tracks, Rauversion.Tracks.Track, on_delete: :delete_all
has_many :playlists, Rauversion.Playlists.Playlist, on_delete: :delete_all

has_many :followings, Rauversion.UserFollows.UserFollow,
foreign_key: :following_id,
on_delete: :delete_all

has_many :followers, Rauversion.UserFollows.UserFollow,
foreign_key: :follower_id,
on_delete: :delete_all

has_many :liked_playlists, Rauversion.PlaylistLikes.PlaylistLike, on_delete: :delete_all

has_many :liked_tracks, Rauversion.TrackLikes.TrackLike, on_delete: :delete_all
has_many :reposted_tracks, Rauversion.Reposts.Repost, on_delete: :delete_all

has_one(:avatar_attachment, ActiveStorage.Attachment,
where: [record_type: "User", name: "avatar"],
Expand Down
21 changes: 21 additions & 0 deletions lib/rauversion/blob_utils.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
defmodule Rauversion.BlobUtils do
def create_blob(file) do
ActiveStorage.Blob.create_and_upload!(
%ActiveStorage.Blob{},
io: {:path, file.path},
filename: file.filename,
content_type: file.content_type,
identify: true
)
end

#  TODO: maybe copy here the live-upload
def attach_file_with_blob(struct, kind, file) do
blob = Rauversion.BlobUtils.create_blob(file)
Rauversion.BlobUtils.attach_file(struct, kind, blob)
end

def attach_file(struct, kind, blob) do
cover = apply(struct.data.__struct__, :"#{kind}", [struct.data])
apply(cover.__struct__, :attach, [cover, blob])
end

def fallback_image(url \\ nil) do
RauversionWeb.Router.Helpers.static_path(
RauversionWeb.Endpoint,
Expand Down
62 changes: 62 additions & 0 deletions lib/rauversion/category_types.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
defmodule Rauversion.CategoryTypes do
def genres do
[
"Alternative Rock",
"Ambient",
"Classical",
"Country ",
"Dance & EDM",
"Dancehall",
"Deep House",
"Disco",
"Drum & Bass",
"Dubstep",
"Electronic",
"Folk & Singer-Songwriter",
"Hip-hop & Rap",
"House",
"Indie",
"Jazz & Blues",
"Latin",
"Metal",
"Piano",
"Pop",
"R&B & Soul",
"Reggae",
"Reggaeton",
"Rock",
"Soundtrack",
"Techno",
"Trance",
"Trap",
"Triphop",
"World"
]
end

def music_genres do
[
"Audiobooks",
"Business",
"Comedy",
"Entertainment",
"Learning",
"News & Politics",
"Religion & Spirituality",
"Science",
"Sports",
"Storytelling",
"Technology"
]
end

def playlist_types do
[
"playlist",
"album",
"ep",
"single",
"compilation"
]
end
end
104 changes: 104 additions & 0 deletions lib/rauversion/playlist_likes.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
defmodule Rauversion.PlaylistLikes do
@moduledoc """
The PlaylistLikes context.
"""

import Ecto.Query, warn: false
alias Rauversion.Repo

alias Rauversion.PlaylistLikes.PlaylistLike

@doc """
Returns the list of playlist_likes.
## Examples
iex> list_playlist_likes()
[%PlaylistLike{}, ...]
"""
def list_playlist_likes do
Repo.all(PlaylistLike)
end

@doc """
Gets a single playlist_like.
Raises `Ecto.NoResultsError` if the Playlist like does not exist.
## Examples
iex> get_playlist_like!(123)
%PlaylistLike{}
iex> get_playlist_like!(456)
** (Ecto.NoResultsError)
"""
def get_playlist_like!(id), do: Repo.get!(PlaylistLike, id)

@doc """
Creates a playlist_like.
## Examples
iex> create_playlist_like(%{field: value})
{:ok, %PlaylistLike{}}
iex> create_playlist_like(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_playlist_like(attrs \\ %{}) do
%PlaylistLike{}
|> PlaylistLike.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a playlist_like.
## Examples
iex> update_playlist_like(playlist_like, %{field: new_value})
{:ok, %PlaylistLike{}}
iex> update_playlist_like(playlist_like, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_playlist_like(%PlaylistLike{} = playlist_like, attrs) do
playlist_like
|> PlaylistLike.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a playlist_like.
## Examples
iex> delete_playlist_like(playlist_like)
{:ok, %PlaylistLike{}}
iex> delete_playlist_like(playlist_like)
{:error, %Ecto.Changeset{}}
"""
def delete_playlist_like(%PlaylistLike{} = playlist_like) do
Repo.delete(playlist_like)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking playlist_like changes.
## Examples
iex> change_playlist_like(playlist_like)
%Ecto.Changeset{data: %PlaylistLike{}}
"""
def change_playlist_like(%PlaylistLike{} = playlist_like, attrs \\ %{}) do
PlaylistLike.changeset(playlist_like, attrs)
end
end
17 changes: 17 additions & 0 deletions lib/rauversion/playlist_likes/playlist_like.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Rauversion.PlaylistLikes.PlaylistLike do
use Ecto.Schema
import Ecto.Changeset

schema "playlist_likes" do
belongs_to :user, Rauversion.Accounts.User
belongs_to :playlist, Rauversion.Playlists.Playlist
timestamps()
end

@doc false
def changeset(playlist_like, attrs) do
playlist_like
|> cast(attrs, [:user_id, :playlist_id])
|> validate_required([:user_id, :playlist_id])
end
end
Loading

0 comments on commit 77068e7

Please sign in to comment.