Compare commits

...

4 Commits

Author SHA1 Message Date
Ryan Rix 92d35fde32 make it a bit easier to walk through readme 2020-09-17 11:28:00 -07:00
Ryan Rix a1cda69ee8 switch to waffle from arc, store images in priv/uploads 2020-09-17 11:27:46 -07:00
Ryan Rix a56004c4ea Link to large image from thumbnail 2020-09-17 11:26:53 -07:00
Ryan Rix ed84b85525 Pass params in to Thing.new(with_photos: true) 2020-09-17 11:26:22 -07:00
7 changed files with 44 additions and 34 deletions

View File

@ -51,14 +51,7 @@ There is a [[file:Makefile][Makefile]] to make it easier to tangle the files. Yo
Poka Ijo development requires a postgres database with a database called =poka_ijo_dev=. run [[shell:mix ecto.setup]] (or click on that link!)
Alchemist runs an IEx shell:
#+begin_src emacs-lisp
(use-package alchemist)
(alchemist-iex-run " -S mix phx.server")
#+end_src
Executing this code will allow you to send the org-babel block under point to the REPL. I don't know how that handles =noweb=, blocks but it kinda works.
Executing this code will allow you to send the org-babel block under point to the REPL. I don't know how that handles =noweb=, blocks but it kinda works. (it doesn't even tangle them before sending to REPL, i've been relying on the phoenix dev server file watch)
#+begin_src emacs-lisp
(use-package eval-in-repl
@ -86,9 +79,17 @@ Executing this code will allow you to send the org-babel block under point to th
(evil-define-key 'normal 'org-mode-map (kbd "M-<return>") #'ober-eval-block-in-repl))
#+end_src
Alchemist runs an IEx shell:
#+begin_src emacs-lisp
(use-package alchemist)
(alchemist-iex-run " -S mix phx.server")
#+end_src
Run this with Alt-Return to disable colors and see the =IEx= shell in action. You can run any[fn:1] source block in this fashion.
#+begin_src elixir
alias PokaIjo.{Repo,Thing,Photo}
IEx.configure(colors: [enabled: false])
#+end_src

View File

@ -32,4 +32,6 @@
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.5.0", "8516502659002cec19e244ebd90d312183064be95025a319a6c7e89f4bccd65b", [:rebar3], [], "hexpm", "d48d002e15f5cc105a696cf2f1bbb3fc72b4b770a184d8420c8db20da2674b38"},
"waffle": {:hex, :waffle, "1.1.3", "1caef3cd99f95495e503ddb1974cd48ecf9015d9534cc75ae909a5be701ca666", [:mix], [{:ex_aws, "~> 2.1.2", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:ex_aws_s3, "~> 2.0", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "020156a79e85d18768db9a9d2295d4b3b962e193942ff25ae64d0d3e3f503714"},
"waffle_ecto": {:hex, :waffle_ecto, "0.0.9", "d61b0b6a1547f42a7a0fa6efff8389ac4219dbbe45fcf7a2add4c923f416cd85", [:mix], [{:ecto, ">= 2.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:waffle, "~> 1.0", [hex: :waffle, repo: "hexpm", optional: false]}], "hexpm", "994cd5a08134b3d19ba5930b7b56c329557909b0d41c7bc3ab0aef6c5b07aa32"},
}

View File

@ -6,7 +6,7 @@ This file describes the general Elixir and Phoenix plumbing required to get any
* Project =.gitignore= file
This project is intended to be developed as a [[file:~/Code/phx_new_literate/templates/literate_programming.org][Literate Programming]] [[file:~/Code/phx_new_literate/templates/org-mode.org][org-mode]] application, developed within my [[file:~/Code/phx_new_literate/templates/org-roam.org][org-roam]] environment, published as part of my [[file:~/Code/phx_new_literate/templates/arcology.org][Arcology]] system. The project is its own subdirectory under my =org-roam-directory= and it can be on yours as well, or provided standalone.
This project is intended to be developed as a [[file:~/org/cce/literate_programming.org][Literate Programming]] [[file:~/org/org-mode.org][org-mode]] application, developed within my [[file:~/org/cce/org-roam.org][org-roam]] environment, published as part of my [[file:~/org/arcology.org][Arcology]] system. The project is its own subdirectory under my =org-roam-directory= and it can be on yours as well, or provided standalone.
The repo will contain docs and assets and a build script that will call up an [[file:../Emacs.org][Emacs]] that will "tangle" the files out and build the application. It will *not* contain the compiled code checked in, the docs must be considered the source of truth. We'll have facilities to "de-tangle" the source code eventually to aide contribution from folks who aren't running Emacs. For now, though, I'm gonna be a bastard 😄
@ -133,8 +133,8 @@ The project dependencies are specified here, this is a simple Phoenix web app fo
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:arc, "~> 0.11.0"},
{:arc_ecto, "~> 0.11.0"},
{:waffle, "~> 1.1.0"},
{:waffle_ecto, "~> 0.0.9"},
{:mix_test_watch, "~> 1.0", only: :dev, runtime: false},
]
end
@ -225,8 +225,9 @@ config :phoenix, :json_library, Jason
For [[file:photo_uploads.org][PokaIjo.Photo]], I upload the photos to my local filesystem. If it becomes a problem I'll use B2 via S3.
#+begin_src elixir :tangle config/config.exs
config :arc,
storage: Arc.Storage.Local
config :waffle,
storage: Waffle.Storage.Local,
storage_dir_prefix: "priv/uploads/"
#+end_src
Lastly, config.exs loads environment-specific configuration.
@ -241,7 +242,7 @@ import_config "#{Mix.env()}.exs"
use Mix.Config
#+end_src
The database configuration for local development is pretty simple, a local postgres instance is required, which makes it a bit heavy to do on older hardware, but this is an Elixir decision not mine. There is a sqlite for ecto2, but I only use that in the [[file:../arcology.org][§Arcology]] project right now.
The database configuration for local development is pretty simple, a local postgres instance is required, which makes it a bit heavy to do on older hardware, but this is an Elixir decision not mine. There is a sqlite for ecto2, but I only use that in the [[file:../arcology.org][Arcology]] project right now.
#+begin_src elixir :tangle config/dev.exs
config :poka_ijo, PokaIjo.Repo,

View File

@ -2,16 +2,16 @@
#+ROAM_ALIAS: "PokaIjo.Photo"
#+PROPERTY: header-args:elixir :results none
I use [[https://github.com/stavro/arc][stavro/arc]] and its ecto module to provide photo upload and cleanup capabilities. It relies on ImageMagick being installed, I'll deal with that when I write my deployment documentation!
I use [[https://github.com/waffle-elixir][Waffle]] and its [[https://github.com/elixir-waffle/waffle_ecto][ecto module]] to provide photo upload and cleanup capabilities. It relies on ImageMagick being installed, I'll deal with that when I write my deployment documentation!
* Ecto Model
The persistence model is a pretty simple Ecto model, it's got a single association to a thing, a reference to an object of the =Arc.Definition=, and a UUID used for the filename. Eventually I need to add a =delete_photo= call, but for now this is Good Enough, there's very little behavior to consider here.
The persistence model is a pretty simple Ecto model, it's got a single association to a thing, a reference to an object of the =Waffle.Definition=, and a UUID used for the filename. Eventually I need to add a =delete_photo= call, but for now this is Good Enough, there's very little behavior to consider here.
#+begin_src elixir :noweb-ref ecto-schema-and-fns
use Ecto.Schema
use Arc.Ecto.Schema
use Arc.Ecto.Definition
use Waffle.Ecto.Schema
use Waffle.Ecto.Definition
import Ecto.Changeset
schema "photos" do
@ -38,17 +38,19 @@ def create_photo(%Thing{} = thing, attrs \\ %{}) do
end
#+end_src
* Arc Definition
* Waffle Definition
This =Arc.Definition= creates a pair of stripped images for each photo uploaded; I have the metadata-rich versions saved on my phone if I need them, and I'd rather not have things laying around that have my home GPS coordinates on 'em, you know? Some folks will balk at my only providing =1000x1000= max images, we'll see if I regret that!
This =Waffle.Definition= creates a pair of stripped images for each photo uploaded; I have the metadata-rich versions saved on my phone if I need them, and I'd rather not have things laying around that have my home GPS coordinates on 'em, you know? Some folks will balk at my only providing =1000x1000= max images, we'll see if I regret that!
#+begin_src elixir :noweb-ref arc-definition
use Arc.Definition
use Arc.Ecto.Definition
#+begin_src elixir :noweb-ref waffle-definition
use Waffle.Definition
@versions [:thumb, :large]
# Whitelist file extensions:
def validate({file, _}) do
~w(.jpg .jpeg .gif .png .webp) |> Enum.member?(Path.extname(file.file_name))
~w(.jpg .jpeg .gif .png .webp)
|> Enum.member?(Path.extname(file.file_name))
end
# Define a thumbnail transformation:
@ -67,7 +69,7 @@ end
# Override the storage directory:
def storage_dir(_, _) do
"uploads/photos/"
"/uploads/photos/"
end
#+end_src
@ -91,14 +93,13 @@ defmodule PhotoGallery.Repo.Migrations.CreatePhotos do
end
#+end_src
* Assemblage
#+begin_src elixir :tangle lib/poka_ijo/photo.ex :noweb yes
defmodule PokaIjo.Photo do
alias PokaIjo.{Thing,Photo,Repo}
<<arc-definition>>
<<waffle-definition>>
<<ecto-schema-and-fns>>
end
#+end_src

View File

@ -106,7 +106,7 @@ defmodule PokaIjoWeb.Endpoint do
<<plug-configurations>>
<<plug-session>>
<<plug-uploads>>
<<Plug-Static>>
<<plug-static>>
plug PokaIjoWeb.Router
end
@ -114,7 +114,7 @@ end
Serve at "/" the static files from "priv/static" directory. Since we will use =phx.digest= we can =gzip= the assets.
#+begin_src elixir :noweb-ref Plug-Static
#+begin_src elixir :noweb-ref plug-static
plug Plug.Static,
at: "/",
from: :poka_ijo,
@ -122,11 +122,14 @@ plug Plug.Static,
only: ~w(css fonts images js favicon.ico robots.txt)
#+end_src
These uploads are used by [[file:photo_uploads.org][PokaIjo.Photo]], I'll eventually want to move this in to a configurable element.
#+begin_src elixir :noweb-ref plug-uploads
plug Plug.Static,
at: "/uploads",
from: Path.expand("./uploads"),
gzip: false
from: {:poka_ijo, "priv/uploads"},
gzip: false,
only: ~w(photos)
#+end_src
Code Reloading is enabled in local development by inserting some plugs if the =code_reloading?/0= function from =Phoenix.Endpoint= returns true based on [[id:11e43150-7556-45a9-978e-05e942d40a68][Mix configuration]].

View File

@ -135,7 +135,9 @@ end
<%= if Enum.count(@thing.photos) > 0 do %>
<div class="grid-x small-up-2 medium-up-4">
<%= for img <- @thing.photos do %>
<%= img_tag PokaIjo.Photo.url({img.photo, img}, :thumb), class: "thumbnail cell" %>
<%= link to: PokaIjo.Photo.url({img.photo, img}, :large) do %>
<%= img_tag PokaIjo.Photo.url({img.photo, img}, :thumb), class: "thumbnail cell" %>
<% end %>
<% end %>
</div>
<% end %>
@ -720,7 +722,7 @@ defmodule PokaIjoWeb.ThingController do
use PokaIjoWeb, :controller
require Logger
alias PokaIjo.{Repo, Photo, Thing}
alias PokaIjo.Thing
<<controller-index>>
<<controller-show>>

View File

@ -89,7 +89,7 @@ These functions aid in the creation and update of Things.
end
def new params, with_photo: true do
Thing.changeset(%Thing{photos: [%Photo{}]})
Thing.changeset(%Thing{photos: [%Photo{}]}, params)
end
def new do