Compare commits
4 Commits
67a63e42c3
...
92d35fde32
Author | SHA1 | Date |
---|---|---|
Ryan Rix | 92d35fde32 | |
Ryan Rix | a1cda69ee8 | |
Ryan Rix | a56004c4ea | |
Ryan Rix | ed84b85525 |
17
README.org
17
README.org
|
@ -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
|
||||
|
||||
|
|
2
mix.lock
2
mix.lock
|
@ -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"},
|
||||
}
|
||||
|
|
13
phoenix.org
13
phoenix.org
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]].
|
||||
|
|
|
@ -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>>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue