Current section
37 Versions
Jump to
Current section
37 Versions
Compare versions
24
files changed
+286
additions
-63
deletions
| @@ -42,7 +42,7 @@ _If you are having problems, view `README_INSTALL.md` for manual instructions._ | |
| 42 42 | |
| 43 43 | ```elixir |
| 44 44 | def deps do |
| 45 | - [{:thesis, "~> 0.0.25"}] |
| 45 | + [{:thesis, "~> 0.0.26"}] |
| 46 46 | end |
| 47 47 | |
| 48 48 | def application do |
| @@ -159,12 +159,42 @@ content type. | |
| 159 159 | becomes... |
| 160 160 | |
| 161 161 | ```eex |
| 162 | - <%= content(@conn, "Image identifier", :background_image, do: "http://placekitten.com/200/300") |
| 163 | - %> |
| 162 | + <%= content(@conn, "Image identifier", :background_image, do: "http://placekitten.com/200/300") %> |
| 164 163 | ``` |
| 165 164 | |
| 166 165 | ### Image Uploads |
| 167 166 | |
| 167 | + Thesis offers support for a few different ways to handle image uploads: store files in the database, |
| 168 | + point to an uploader/adapter inside your custom app, or use one of the prebuilt adapters. |
| 169 | + |
| 170 | + ##### Store Files in Database |
| 171 | + For smaller websites and/or website that are hosted on the cloud, thesis offers a no-setup-required image uploader. |
| 172 | + Files are stored in a separate table and contain all of the needed metadata (name, file type, and blobs themselves). |
| 173 | + Keep in mind as you upload more and more files, your database will grow quickly. Don't use this for high-traffic, |
| 174 | + content-heavy web applications. Smaller personal websites are probably fine. |
| 175 | + |
| 176 | + To enable, add this in your config/config.exs file: |
| 177 | + |
| 178 | + ```elixir |
| 179 | + config :thesis, |
| 180 | + uploader: Thesis.RepoUploader |
| 181 | + ``` |
| 182 | + |
| 183 | + ##### Use Your Own Uploader Module |
| 184 | + |
| 185 | + If you already set up file uploads in your custom app, point thesis to a module that can handle a `%Plug.Upload{}` |
| 186 | + struct. |
| 187 | + |
| 188 | + ```elixir |
| 189 | + config :thesis, |
| 190 | + uploader: <MyApp>.<CustomUploaderModule> |
| 191 | + ``` |
| 192 | + |
| 193 | + The module should have an `upload/1` function that accepts a `%Plug.Upload{}` struct. This function should return either `{:ok, "path/to/file.jpg"}` tuple with an image url or path, or {:error, _}. You can view |
| 194 | + [/lib/thesis/uploaders/repo_uploader.ex](https://github.com/infinitered/thesis-phoenix/blob/master/lib/thesis/uploaders/repo_uploader.ex) |
| 195 | + for an example. |
| 196 | + |
| 197 | + ##### Use a Prebuilt Adapter |
| 168 198 | Included in Thesis is an adapter for Ospry.io, which is a service that |
| 169 199 | offers the first 1,000 images and 1 GB of monthly download bandwidth |
| 170 200 | for free. |
| @@ -172,16 +202,19 @@ for free. | |
| 172 202 | 1. Sign up at [https://ospry.io/sign-up](https://ospry.io/sign-up) |
| 173 203 | 2. Verify your email |
| 174 204 | 3. Create a production subdomain (assets.example.com) |
| 175 | - 3. Copy your production public key to the Thesis config: |
| 205 | + 4. Add a valid credit card if you anticipate exceeding Ospry.io limits. |
| 206 | + 5. Copy your production public key to the Thesis config: |
| 176 207 | |
| 177 208 | ```elixir |
| 209 | + config :thesis, |
| 210 | + uploader: Thesis.OspryUploader |
| 211 | + |
| 178 212 | config :thesis, Thesis.OspryUploader, |
| 179 213 | ospry_public_key: "pk-prod-abcdefghijklmnopqrstuvwxyz0123456789" |
| 180 214 | ``` |
| 181 215 | |
| 182 216 | That's it! Restart your server and image content areas will now contain a |
| 183 | - file upload field. _Note: You'll need to add a valid credit card if you |
| 184 | - anticipate exceeding Ospry.io limits._ |
| 217 | + file upload field. |
| 185 218 | |
| 186 219 | ### Global Content Areas |
| @@ -6,7 +6,7 @@ For automatic setup, see `README.md`. | |
| 6 6 | |
| 7 7 | ```elixir |
| 8 8 | def deps do |
| 9 | - [{:thesis, "~> 0.0.25"}] |
| 9 | + [{:thesis, "~> 0.0.26"}] |
| 10 10 | end |
| 11 11 | |
| 12 12 | def application do |
| @@ -21,17 +21,19 @@ Run `mix deps.get`. | |
| 21 21 | ```elixir |
| 22 22 | config :thesis, |
| 23 23 | store: Thesis.EctoStore, |
| 24 | - authorization: <MyApp>.ThesisAuth |
| 24 | + authorization: <MyApp>.ThesisAuth, |
| 25 | + uploader: Thesis.RepoUploader |
| 26 | + # uploader: <MyApp>.<CustomUploaderModule> |
| 27 | + # uploader: Thesis.OspryUploader |
| 25 28 | config :thesis, Thesis.EctoStore, repo: <MyApp>.Repo |
| 29 | + # config :thesis, Thesis.OspryUploader, |
| 30 | + # ospry_public_key: "pk-prod-asdfasdfasdfasdf" |
| 26 31 | # If you want to allow creating dynamic pages: |
| 27 32 | # config :thesis, :dynamic_pages, |
| 28 33 | # view: <MyApp>.PageView, |
| 29 34 | # templates: ["index.html", "otherview.html"], |
| 30 35 | # not_found_view: <MyApp>.ErrorView, |
| 31 36 | # not_found_template: "404.html" |
| 32 | - # If you want to use Ospry.io file uploads: |
| 33 | - # config :thesis, Thesis.OspryUploader, |
| 34 | - # ospry_public_key: "pk-prod-asdfasdfasdfasdfasdf" |
| 35 37 | ``` |
| 36 38 | |
| 37 39 | #### 3. Create `lib/thesis_auth.ex` |
| @@ -7,18 +7,20 @@ | |
| 7 7 | [<<"lib/mix/tasks/thesis.install.ex">>,<<"lib/mix/utils.ex">>, |
| 8 8 | <<"lib/thesis.ex">>,<<"lib/thesis/api_controller.ex">>, |
| 9 9 | <<"lib/thesis/auth.ex">>,<<"lib/thesis/config.ex">>, |
| 10 | - <<"lib/thesis/controller.ex">>,<<"lib/thesis/models/page.ex">>, |
| 11 | - <<"lib/thesis/models/page_content.ex">>,<<"lib/thesis/render.ex">>, |
| 12 | - <<"lib/thesis/router.ex">>,<<"lib/thesis/stores/ecto_store.ex">>, |
| 13 | - <<"lib/thesis/stores/store.ex">>, |
| 14 | - <<"lib/thesis/uploaders/ospry_uploader.ex">>, |
| 10 | + <<"lib/thesis/controller.ex">>,<<"lib/thesis/models/file.ex">>, |
| 11 | + <<"lib/thesis/models/page.ex">>,<<"lib/thesis/models/page_content.ex">>, |
| 12 | + <<"lib/thesis/render.ex">>,<<"lib/thesis/router.ex">>, |
| 13 | + <<"lib/thesis/stores/ecto_store.ex">>,<<"lib/thesis/stores/store.ex">>, |
| 14 | + <<"lib/thesis/uploaders/repo_uploader.ex">>, |
| 15 15 | <<"lib/thesis/uploaders/s3_uploader.ex">>, |
| 16 | - <<"lib/thesis/uploaders/uploader.ex">>,<<"lib/thesis/view.ex">>, |
| 17 | - <<"priv/static/thesis.css">>,<<"priv/static/thesis.js">>, |
| 16 | + <<"lib/thesis/uploaders/uploader.ex">>,<<"lib/thesis/utilities.ex">>, |
| 17 | + <<"lib/thesis/view.ex">>,<<"priv/static/thesis.css">>, |
| 18 | + <<"priv/static/thesis.js">>, |
| 18 19 | <<"priv/templates/thesis.install/add_indexes_to_tables.exs">>, |
| 19 20 | <<"priv/templates/thesis.install/add_meta_to_thesis_page_contents.exs">>, |
| 20 21 | <<"priv/templates/thesis.install/add_template_and_redirect_url_to_thesis_pages.exs">>, |
| 21 22 | <<"priv/templates/thesis.install/change_content_default_for_page_content.exs">>, |
| 23 | + <<"priv/templates/thesis.install/create_thesis_files_table.exs">>, |
| 22 24 | <<"priv/templates/thesis.install/create_thesis_tables.exs">>, |
| 23 25 | <<"priv/templates/thesis.install/thesis_auth.exs">>, |
| 24 26 | <<"web/static/css/_extends/_extends.sass">>, |
| @@ -136,7 +138,7 @@ | |
| 136 138 | <<"README_INSTALL.md">>,<<"LICENSE.md">>,<<"package.json">>]}. |
| 137 139 | {<<"licenses">>,[<<"MIT">>]}. |
| 138 140 | {<<"links">>, |
| 139 | - [{<<"Docs">>,<<"https://hexdocs.pm/thesis/0.0.25/api-reference.html">>}, |
| 141 | + [{<<"Docs">>,<<"https://hexdocs.pm/thesis/0.0.26/api-reference.html">>}, |
| 140 142 | {<<"GitHub">>,<<"https://github.com/infinitered/thesis">>}]}. |
| 141 143 | {<<"maintainers">>, |
| 142 144 | [<<"Jamon Holmgren">>,<<"Yulian Glukhenko">>,<<"Ken Miller">>, |
| @@ -167,4 +169,4 @@ | |
| 167 169 | {<<"name">>,<<"html_sanitize_ex">>}, |
| 168 170 | {<<"optional">>,false}, |
| 169 171 | {<<"requirement">>,<<">= 1.0.1">>}]]}. |
| 170 | - {<<"version">>,<<"0.0.25">>}. |
| 172 | + {<<"version">>,<<"0.0.26">>}. |
| @@ -7,7 +7,8 @@ defmodule Mix.Tasks.Thesis.Install do | |
| 7 7 | "add_meta_to_thesis_page_contents", |
| 8 8 | "add_indexes_to_tables", |
| 9 9 | "add_template_and_redirect_url_to_thesis_pages", |
| 10 | - "change_content_default_for_page_content" |
| 10 | + "change_content_default_for_page_content", |
| 11 | + "create_thesis_files_table" |
| 11 12 | ] |
| 12 13 | @template_files [ |
| 13 14 | {"priv/templates/thesis.install/thesis_auth.exs", "lib/thesis_auth.ex"} |
| @@ -103,17 +104,19 @@ defmodule Mix.Tasks.Thesis.Install do | |
| 103 104 | # Configure thesis content editor |
| 104 105 | config :thesis, |
| 105 106 | store: Thesis.EctoStore, |
| 106 | - authorization: #{Mix.Phoenix.base}.ThesisAuth |
| 107 | - config :thesis, Thesis.EctoStore, repo: #{Mix.Phoenix.base}.Repo |
| 107 | + authorization: #{Mix.Phoenix.base}.ThesisAuth, |
| 108 | + uploader: Thesis.RepoUploader |
| 109 | + # uploader: <MyApp>.<CustomUploaderModule> |
| 110 | + # uploader: Thesis.OspryUploader |
| 111 | + config :thesis, Thesis.EctoStore, repo: <MyApp>.Repo |
| 112 | + # config :thesis, Thesis.OspryUploader, |
| 113 | + # ospry_public_key: "pk-prod-asdfasdfasdfasdf" |
| 108 114 | # If you want to allow creating dynamic pages: |
| 109 115 | # config :thesis, :dynamic_pages, |
| 110 116 | # view: #{Mix.Phoenix.base}.PageView, |
| 111 117 | # templates: ["index.html", "otherview.html"], |
| 112 118 | # not_found_view: #{Mix.Phoenix.base}.ErrorView, |
| 113 119 | # not_found_template: "404.html" |
| 114 | - # If you want to use Ospry.io file uploads: |
| 115 | - # config :thesis, Thesis.OspryUploader, |
| 116 | - # ospry_public_key: "pk-prod-asdfasdfasdfasdfasdf" |
| 117 120 | """ |
| 118 121 | end |
| 119 122 | end |
| @@ -18,6 +18,32 @@ defmodule Thesis.ApiController do | |
| 18 18 | json conn, %{} |
| 19 19 | end |
| 20 20 | |
| 21 | + def upload_file(conn, %{"file" => ""}), do: json conn, %{path: ""} |
| 22 | + def upload_file(conn, %{"file" => file}) do |
| 23 | + case uploader.upload(file) do |
| 24 | + {:ok, path} -> json conn, %{path: path} |
| 25 | + {:error, _} -> json conn, %{path: ""} |
| 26 | + end |
| 27 | + end |
| 28 | + def upload_file(conn, _), do: json conn, %{path: ""} |
| 29 | + |
| 30 | + def show_file(conn, %{"slug" => slug}) do |
| 31 | + file = store.file(slug) |
| 32 | + do_show_file(conn, file) |
| 33 | + end |
| 34 | + |
| 35 | + defp do_show_file(conn, nil) do |
| 36 | + conn |
| 37 | + |> put_resp_content_type("text/plain; charset=UTF-8") |
| 38 | + |> send_resp(404, "File Not Found") |
| 39 | + end |
| 40 | + |
| 41 | + defp do_show_file(conn, file) do |
| 42 | + conn |
| 43 | + |> put_resp_content_type(file.content_type) |
| 44 | + |> send_resp(200, file.data) |
| 45 | + end |
| 46 | + |
| 21 47 | defp ensure_authorized!(conn, _params) do |
| 22 48 | if auth.page_is_editable?(conn), do: conn, else: put_unauthorized(conn) |
| 23 49 | end |
Loading more files…