Current section

37 Versions

Jump to

Compare versions

32 files changed
+2234 additions
-15 deletions
  @@ -1,20 +1,37 @@
1 1 # Thesis
2 2
3 - **TODO: Add description**
3 + Thesis is an Elixir/Phoenix hex package for quickly and easily adding content
4 + editing to any page.
4 5
5 - ## Installation
6 + It's inspired by the [Rails gem](https://github.com/infinitered/thesis-rails) by
7 + the same name and author.
6 8
7 - If [available in Hex](https://hex.pm/docs/publish), the package can be installed as:
9 + ![2016-03-05-enu58](https://cloud.githubusercontent.com/assets/1479215/13549778/137ec256-e2c2-11e5-8c6e-7cd653cbd52b.gif)
8 10
9 - 1. Add thesis to your list of dependencies in `mix.exs`:
11 + ## Installation and Configuration
10 12
11 - def deps do
12 - [{:thesis, "~> 0.0.1"}]
13 - end
13 + 1. Add thesis to your `mix.exs`:
14 14
15 - 2. Ensure thesis is started before your application:
15 + ```elixir
16 + def deps do
17 + [{:thesis, "~> 0.0.1"}]
18 + end
16 19
17 - def application do
18 - [applications: [:thesis]]
19 - end
20 + def application do
21 + [applications: [:thesis]]
22 + end
23 + ```
24 +
25 + 2. Run `mix thesis.install`
26 +
27 + This will add Thesis to your `package.json`, `config.exs`, generate
28 + a migration, and generate an authorization module.
29 +
30 + ## Making Pages Editable
31 +
32 + TODO
33 +
34 + ## Authorization
35 +
36 + TODO
  @@ -1,12 +1,32 @@
1 1 {<<"app">>,<<"thesis">>}.
2 - {<<"build_tools">>,[]}.
2 + {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,
4 4 <<"Thesis is a lightweight bolt-on content editing system\nfor Phoenix websites.">>}.
5 5 {<<"elixir">>,<<"~> 1.2">>}.
6 - {<<"files">>,[<<"README.md">>]}.
6 + {<<"files">>,
7 + [<<"lib/mix/tasks/thesis.install.ex">>,<<"lib/mix/utils.ex">>,
8 + <<"lib/thesis.ex">>,<<"lib/thesis/api_controller.ex">>,
9 + <<"lib/thesis/config.ex">>,<<"lib/thesis/controller.ex">>,
10 + <<"lib/thesis/models/page.ex">>,<<"lib/thesis/models/page_content.ex">>,
11 + <<"lib/thesis/router.ex">>,<<"lib/thesis/store.ex">>,
12 + <<"lib/thesis/view.ex">>,<<"priv/static/thesis-editor.js">>,
13 + <<"priv/static/thesis-old.js">>,<<"priv/static/thesis.css">>,
14 + <<"priv/static/thesis.js">>,<<"priv/templates/thesis.install/auth.exs">>,
15 + <<"priv/templates/thesis.install/migration.exs">>,
16 + <<"web/static/components/add_button.js">>,
17 + <<"web/static/components/cancel_button.js">>,
18 + <<"web/static/components/delete_button.js">>,
19 + <<"web/static/components/edit_button.js">>,
20 + <<"web/static/components/editor_toolbar.js">>,
21 + <<"web/static/components/page_content_editor.js">>,
22 + <<"web/static/components/save_button.js">>,
23 + <<"web/static/components/settings_button.js">>,
24 + <<"web/static/components/style_button.js">>,
25 + <<"web/static/thesis-editor.js">>,<<"web/static/utilities/net.js">>,
26 + <<"mix.exs">>,<<"README.md">>,<<"package.json">>]}.
7 27 {<<"licenses">>,[<<"MIT">>]}.
8 28 {<<"links">>,
9 - [{<<"Docs">>,<<"https://github.com/infinite_red/thesis/tree/master/docs">>},
29 + [{<<"Docs">>,<<"https://hexdocs.pm/thesis/0.0.2/api-reference.html">>},
10 30 {<<"GitHub">>,<<"https://github.com/infinite_red/thesis">>}]}.
11 31 {<<"maintainers">>,
12 32 [<<"Jamon Holmgren">>,<<"Ken Miller">>,<<"Daniel Berkompas">>]}.
  @@ -32,4 +52,4 @@
32 52 [{<<"app">>,<<"plug">>},
33 53 {<<"optional">>,false},
34 54 {<<"requirement">>,<<"~> 1.0">>}]}]}.
35 - {<<"version">>,<<"0.0.1">>}.
55 + {<<"version">>,<<"0.0.2">>}.
  @@ -0,0 +1,60 @@
1 + defmodule Mix.Tasks.Thesis.Install do
2 + use Mix.Task
3 + import Mix.Thesis.Utils
4 +
5 + @shortdoc "Generates Thesis code in your Phoenix app"
6 +
7 + @moduledoc """
8 + TODO: Write docs.
9 + """
10 +
11 + def run(_args) do
12 + thesis_templates
13 + thesis_npm
14 + thesis_config
15 + end
16 +
17 + def thesis_templates do
18 + template_files = [ {"priv/templates/thesis.install/auth.exs", "lib/auth.ex" } ]
19 + migration_exists = File.ls!("priv/repo/migrations") |> Enum.map(fn (f) -> String.contains?(f, "create_thesis_tables") end) |> Enum.any?
20 + unless migration_exists do
21 + template_files = [{"priv/templates/thesis.install/migration.exs", "priv/repo/migrations/#{timestamp}_create_thesis_tables.exs"} | template_files]
22 + end
23 +
24 + template_files
25 + |> Stream.map(&render_eex/1)
26 + |> Stream.map(&copy_to_target/1)
27 + |> Stream.run
28 + end
29 +
30 + def thesis_npm do
31 + status_msg("updating", "package.json")
32 + System.cmd("npm", ["install", "./deps/thesis", "--save"])
33 + end
34 +
35 + def thesis_config do
36 + status_msg("updating", "config/config.exs")
37 + dest_path = Path.join [File.cwd! | ~w(config)]
38 + dest_file_path = Path.join dest_path, "config.exs"
39 + File.read!(dest_file_path)
40 + |> insert_thesis
41 + |> append_to_file(dest_file_path)
42 + end
43 +
44 + defp insert_thesis(source) do
45 + unless String.contains? source, "config :thesis" do
46 + source <> """
47 +
48 + # Configure thesis content editor
49 + config :thesis,
50 + store: Thesis.Store,
51 + authorization: #{Mix.Phoenix.base}.ThesisAuth
52 + config :thesis, Thesis.Store, repo: #{Mix.Phoenix.base}.Repo
53 + """
54 + else
55 + status_msg("skipping", "thesis config. It already exists.")
56 + :skip
57 + end
58 + end
59 +
60 + end
  @@ -0,0 +1,60 @@
1 + defmodule Mix.Thesis.Utils do
2 +
3 + def get_package_path do
4 + __ENV__.file
5 + |> Path.dirname
6 + |> String.split("/lib/mix")
7 + |> hd
8 + end
9 +
10 + def get_module do
11 + Mix.Project.get
12 + |> Module.split
13 + |> Enum.reverse
14 + |> Enum.at(1)
15 + end
16 +
17 + @doc "Print a status message to the console"
18 + def status_msg(status, message),
19 + do: IO.puts "#{IO.ANSI.green}* #{status}#{IO.ANSI.reset} #{message}"
20 +
21 + @doc "Print an informational message without color"
22 + def debug(message), do: IO.puts "==> #{message}"
23 + @doc "Print an informational message in green"
24 + def info(message), do: IO.puts "==> #{IO.ANSI.green}#{message}#{IO.ANSI.reset}"
25 + @doc "Print a warning message in yellow"
26 + def warn(message), do: IO.puts "==> #{IO.ANSI.yellow}#{message}#{IO.ANSI.reset}"
27 + @doc "Print a notice in yellow"
28 + def notice(message), do: IO.puts "#{IO.ANSI.yellow}#{message}#{IO.ANSI.reset}"
29 + @doc "Print an error message in red"
30 + def error(message), do: IO.puts "==> #{IO.ANSI.red}#{message}#{IO.ANSI.reset}"
31 +
32 + def append_to_file(:skip, _dest_file_path), do: :ok
33 + def append_to_file(contents, dest_file_path) do
34 + File.write! dest_file_path, contents
35 + end
36 +
37 + def render_eex({source, target}) do
38 + source = Path.join(Application.app_dir(:thesis), source)
39 + rendered = EEx.eval_file(source, [base: Mix.Phoenix.base])
40 + {rendered, target}
41 + end
42 +
43 + def copy_to_target({contents, target}) do
44 + if File.exists?(target) do
45 + status_msg("exists", "#{target}")
46 + else
47 + File.write!(target, contents)
48 + end
49 + end
50 +
51 + # Taken from mix phoenix.gen.model
52 + # https://github.com/phoenixframework/phoenix/blob/d3af3397c1f47381dd7ea69869772174a0c1811b/lib/mix/tasks/phoenix.gen.model.ex#L198
53 + def timestamp do
54 + {{y, m, d}, {hh, mm, ss}} = :calendar.universal_time()
55 + "#{y}#{pad(m)}#{pad(d)}#{pad(hh)}#{pad(mm)}#{pad(ss)}"
56 + end
57 +
58 + defp pad(i) when i < 10, do: << ?0, ?0 + i >>
59 + defp pad(i), do: to_string(i)
60 + end
  @@ -0,0 +1,2 @@
1 + defmodule Thesis do
2 + end
Loading more files…