An example AT Protocol application, written in Elixir using atex and Drinkup.
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add atex oauth

+245 -412
+1 -1
.gitignore
··· 6 6 erl_crash.dump 7 7 *.ez 8 8 /tmp/ 9 - statusphere_elixir-*.tar 9 + statusphere-*.tar 10 10 /priv/static/assets/ 11 11 /priv/static/cache_manifest.json 12 12 npm-debug.log
+11 -9
README.md
··· 1 - # StatusphereElixir 1 + # Statusphere 2 2 3 3 To start your Phoenix server: 4 4 5 - * Run `mix setup` to install and setup dependencies 6 - * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server` 5 + - Run `mix setup` to install and setup dependencies 6 + - Start Phoenix endpoint with `mix phx.server` or inside IEx with 7 + `iex -S mix phx.server` 7 8 8 9 Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. 9 10 10 - Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). 11 + Ready to run in production? Please 12 + [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). 11 13 12 14 ## Learn more 13 15 14 - * Official website: https://www.phoenixframework.org/ 15 - * Guides: https://hexdocs.pm/phoenix/overview.html 16 - * Docs: https://hexdocs.pm/phoenix 17 - * Forum: https://elixirforum.com/c/phoenix-forum 18 - * Source: https://github.com/phoenixframework/phoenix 16 + - Official website: https://www.phoenixframework.org/ 17 + - Guides: https://hexdocs.pm/phoenix/overview.html 18 + - Docs: https://hexdocs.pm/phoenix 19 + - Forum: https://elixirforum.com/c/phoenix-forum 20 + - Source: https://github.com/phoenixframework/phoenix
+5 -2
assets/css/app.css
··· 4 4 @import "tailwindcss" source(none); 5 5 @source "../css"; 6 6 @source "../js"; 7 - @source "../../lib/statusphere_elixir_web"; 7 + @source "../../lib/statusphere_web"; 8 8 9 9 /* A Tailwind plugin that makes "hero-#{ICON}" classes available. 10 10 The heroicons installation itself is managed by your mix.exs */ ··· 100 100 @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); 101 101 102 102 /* Make LiveView wrapper divs transparent for layout */ 103 - [data-phx-session], [data-phx-teleported-src] { display: contents } 103 + [data-phx-session], 104 + [data-phx-teleported-src] { 105 + display: contents; 106 + } 104 107 105 108 /* This file is for your main application CSS */
+47 -39
assets/js/app.js
··· 18 18 // To load it, simply add a second `<link>` to your `root.html.heex` file. 19 19 20 20 // Include phoenix_html to handle method=PUT/DELETE in forms and buttons. 21 - import "phoenix_html" 21 + import "phoenix_html"; 22 22 // Establish Phoenix Socket and LiveView configuration. 23 - import {Socket} from "phoenix" 24 - import {LiveSocket} from "phoenix_live_view" 25 - import {hooks as colocatedHooks} from "phoenix-colocated/statusphere_elixir" 26 - import topbar from "../vendor/topbar" 23 + import { Socket } from "phoenix"; 24 + import { LiveSocket } from "phoenix_live_view"; 25 + import { hooks as colocatedHooks } from "phoenix-colocated/statusphere"; 26 + import topbar from "../vendor/topbar"; 27 27 28 - const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") 28 + const csrfToken = document 29 + .querySelector("meta[name='csrf-token']") 30 + .getAttribute("content"); 29 31 const liveSocket = new LiveSocket("/live", Socket, { 30 32 longPollFallbackMs: 2500, 31 - params: {_csrf_token: csrfToken}, 32 - hooks: {...colocatedHooks}, 33 - }) 33 + params: { _csrf_token: csrfToken }, 34 + hooks: { ...colocatedHooks }, 35 + }); 34 36 35 37 // Show progress bar on live navigation and form submits 36 - topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) 37 - window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) 38 - window.addEventListener("phx:page-loading-stop", _info => topbar.hide()) 38 + topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" }); 39 + window.addEventListener("phx:page-loading-start", (_info) => topbar.show(300)); 40 + window.addEventListener("phx:page-loading-stop", (_info) => topbar.hide()); 39 41 40 42 // connect if there are any LiveViews on the page 41 - liveSocket.connect() 43 + liveSocket.connect(); 42 44 43 45 // expose liveSocket on window for web console debug logs and latency simulation: 44 46 // >> liveSocket.enableDebug() 45 47 // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session 46 48 // >> liveSocket.disableLatencySim() 47 - window.liveSocket = liveSocket 49 + window.liveSocket = liveSocket; 48 50 49 51 // The lines below enable quality of life phoenix_live_reload 50 52 // development features: ··· 53 55 // 2. click on elements to jump to their definitions in your code editor 54 56 // 55 57 if (process.env.NODE_ENV === "development") { 56 - window.addEventListener("phx:live_reload:attached", ({detail: reloader}) => { 57 - // Enable server log streaming to client. 58 - // Disable with reloader.disableServerLogs() 59 - reloader.enableServerLogs() 58 + window.addEventListener( 59 + "phx:live_reload:attached", 60 + ({ detail: reloader }) => { 61 + // Enable server log streaming to client. 62 + // Disable with reloader.disableServerLogs() 63 + reloader.enableServerLogs(); 60 64 61 - // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component 62 - // 63 - // * click with "c" key pressed to open at caller location 64 - // * click with "d" key pressed to open at function component definition location 65 - let keyDown 66 - window.addEventListener("keydown", e => keyDown = e.key) 67 - window.addEventListener("keyup", _e => keyDown = null) 68 - window.addEventListener("click", e => { 69 - if(keyDown === "c"){ 70 - e.preventDefault() 71 - e.stopImmediatePropagation() 72 - reloader.openEditorAtCaller(e.target) 73 - } else if(keyDown === "d"){ 74 - e.preventDefault() 75 - e.stopImmediatePropagation() 76 - reloader.openEditorAtDef(e.target) 77 - } 78 - }, true) 65 + // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component 66 + // 67 + // * click with "c" key pressed to open at caller location 68 + // * click with "d" key pressed to open at function component definition location 69 + let keyDown; 70 + window.addEventListener("keydown", (e) => (keyDown = e.key)); 71 + window.addEventListener("keyup", (_e) => (keyDown = null)); 72 + window.addEventListener( 73 + "click", 74 + (e) => { 75 + if (keyDown === "c") { 76 + e.preventDefault(); 77 + e.stopImmediatePropagation(); 78 + reloader.openEditorAtCaller(e.target); 79 + } else if (keyDown === "d") { 80 + e.preventDefault(); 81 + e.stopImmediatePropagation(); 82 + reloader.openEditorAtDef(e.target); 83 + } 84 + }, 85 + true 86 + ); 79 87 80 - window.liveReloader = reloader 81 - }) 88 + window.liveReloader = reloader; 89 + } 90 + ); 82 91 } 83 -
+11 -7
config/config.exs
··· 7 7 # General application configuration 8 8 import Config 9 9 10 - config :statusphere_elixir, 11 - ecto_repos: [StatusphereElixir.Repo], 10 + config :statusphere, 11 + ecto_repos: [Statusphere.Repo], 12 12 generators: [timestamp_type: :utc_datetime, binary_id: true] 13 13 14 14 # Configure the endpoint 15 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 15 + config :statusphere, StatusphereWeb.Endpoint, 16 16 url: [host: "localhost"], 17 17 adapter: Bandit.PhoenixAdapter, 18 18 render_errors: [ 19 - formats: [html: StatusphereElixirWeb.ErrorHTML, json: StatusphereElixirWeb.ErrorJSON], 19 + formats: [html: StatusphereWeb.ErrorHTML, json: StatusphereWeb.ErrorJSON], 20 20 layout: false 21 21 ], 22 - pubsub_server: StatusphereElixir.PubSub, 22 + pubsub_server: Statusphere.PubSub, 23 23 live_view: [signing_salt: "t+91lIqk"] 24 24 25 25 # Configure esbuild (the version is required) 26 26 config :esbuild, 27 27 version: "0.25.4", 28 - statusphere_elixir: [ 28 + statusphere: [ 29 29 args: 30 30 ~w(js/app.js --bundle --target=es2022 --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:@=.), 31 31 cd: Path.expand("../assets", __DIR__), ··· 35 35 # Configure tailwind (the version is required) 36 36 config :tailwind, 37 37 version: "4.1.12", 38 - statusphere_elixir: [ 38 + statusphere: [ 39 39 args: ~w( 40 40 --input=assets/css/app.css 41 41 --output=priv/static/assets/css/app.css ··· 56 56 57 57 # Use Jason for JSON parsing in Phoenix 58 58 config :phoenix, :json_library, Jason 59 + 60 + config :atex, Atex.OAuth, 61 + scopes: ["transition:generic"], 62 + key_id: "statusphere" 59 63 60 64 # Import environment specific config. This must remain at the bottom 61 65 # of this file so it overrides the configuration defined above.
+15 -9
config/dev.exs
··· 1 1 import Config 2 2 3 3 # Configure your database 4 - config :statusphere_elixir, StatusphereElixir.Repo, 5 - database: Path.expand("../statusphere_elixir_dev.db", __DIR__), 4 + config :statusphere, Statusphere.Repo, 5 + database: Path.expand("../statusphere_dev.db", __DIR__), 6 6 pool_size: 5, 7 7 stacktrace: true, 8 8 show_sensitive_data_on_connection_error: true ··· 13 13 # The watchers configuration can be used to run external 14 14 # watchers to your application. For example, we can use it 15 15 # to bundle .js and .css sources. 16 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 16 + config :statusphere, StatusphereWeb.Endpoint, 17 17 # Binding to loopback ipv4 address prevents access from other machines. 18 18 # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. 19 19 http: [ip: {127, 0, 0, 1}], ··· 22 22 debug_errors: true, 23 23 secret_key_base: "YjHndGQyYIEkOsJtZzle8dUtbznbvM2CwGhF7NSoWxgSTIGpouNbVIND7cAmnWfB", 24 24 watchers: [ 25 - esbuild: {Esbuild, :install_and_run, [:statusphere_elixir, ~w(--sourcemap=inline --watch)]}, 26 - tailwind: {Tailwind, :run, [:statusphere_elixir, ~w(--watch)]} 25 + esbuild: {Esbuild, :install_and_run, [:statusphere, ~w(--sourcemap=inline --watch)]}, 26 + tailwind: {Tailwind, :run, [:statusphere, ~w(--watch)]} 27 27 ] 28 28 29 29 # ## SSL Support ··· 50 50 # different ports. 51 51 52 52 # Reload browser tabs when matching files change. 53 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 53 + config :statusphere, StatusphereWeb.Endpoint, 54 54 live_reload: [ 55 55 web_console_logger: true, 56 56 patterns: [ 57 57 # Static assets, except user uploads 58 58 ~r"priv/static/(?!uploads/).*\.(js|css|png|jpeg|jpg|gif|svg)$", 59 59 # Router, Controllers, LiveViews and LiveComponents 60 - ~r"lib/statusphere_elixir_web/router\.ex$", 61 - ~r"lib/statusphere_elixir_web/(controllers|live|components)/.*\.(ex|heex)$" 60 + ~r"lib/statusphere_web/router\.ex$", 61 + ~r"lib/statusphere_web/(controllers|live|components)/.*\.(ex|heex)$" 62 62 ] 63 63 ] 64 64 65 65 # Enable dev routes for dashboard and mailbox 66 - config :statusphere_elixir, dev_routes: true 66 + config :statusphere, dev_routes: true 67 67 68 68 # Do not include metadata nor timestamps in development logs 69 69 config :logger, :default_formatter, format: "[$level] $message\n" ··· 82 82 debug_attributes: true, 83 83 # Enable helpful, but potentially expensive runtime checks 84 84 enable_expensive_runtime_checks: true 85 + 86 + config :atex, Atex.OAuth, 87 + base_url: "http://127.0.0.1:4000/oauth", 88 + private_key: 89 + "MHcCAQEEIGA8RFx1QUfvdVPD24SvBMS6a0X9fPYx6EPLHttG55ScoAoGCCqGSM49AwEHoUQDQgAEcGzUFa2vMqnevHI5R+QByCmHSCfVy7Uge3VcL5GPVL/tBMeoVizxZey3MUekIHZ981iXW8fTbntYJNXMi2hN5w==", 90 + is_localhost: true
+2 -2
config/prod.exs
··· 5 5 # manifest is generated by the `mix assets.deploy` task, 6 6 # which you should run after static files are built and 7 7 # before starting your production server. 8 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 8 + config :statusphere, StatusphereWeb.Endpoint, 9 9 cache_static_manifest: "priv/static/cache_manifest.json" 10 10 11 11 # Force using SSL in production. This also sets the "strict-security-transport" header, 12 12 # known as HSTS. If you have a health check endpoint, you may want to exclude it below. 13 13 # Note `:force_ssl` is required to be set at compile-time. 14 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 14 + config :statusphere, StatusphereWeb.Endpoint, 15 15 force_ssl: [rewrite_on: [:x_forwarded_proto]], 16 16 exclude: [ 17 17 # paths: ["/health"],
+9 -9
config/runtime.exs
··· 12 12 # If you use `mix release`, you need to explicitly enable the server 13 13 # by passing the PHX_SERVER=true when you start it: 14 14 # 15 - # PHX_SERVER=true bin/statusphere_elixir start 15 + # PHX_SERVER=true bin/statusphere start 16 16 # 17 17 # Alternatively, you can use `mix phx.gen.release` to generate a `bin/server` 18 18 # script that automatically sets the env var above. 19 19 if System.get_env("PHX_SERVER") do 20 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, server: true 20 + config :statusphere, StatusphereWeb.Endpoint, server: true 21 21 end 22 22 23 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 23 + config :statusphere, StatusphereWeb.Endpoint, 24 24 http: [port: String.to_integer(System.get_env("PORT", "4000"))] 25 25 26 26 if config_env() == :prod do ··· 28 28 System.get_env("DATABASE_PATH") || 29 29 raise """ 30 30 environment variable DATABASE_PATH is missing. 31 - For example: /etc/statusphere_elixir/statusphere_elixir.db 31 + For example: /etc/statusphere/statusphere.db 32 32 """ 33 33 34 - config :statusphere_elixir, StatusphereElixir.Repo, 34 + config :statusphere, Statusphere.Repo, 35 35 database: database_path, 36 36 pool_size: String.to_integer(System.get_env("POOL_SIZE") || "5") 37 37 ··· 49 49 50 50 host = System.get_env("PHX_HOST") || "example.com" 51 51 52 - config :statusphere_elixir, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") 52 + config :statusphere, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") 53 53 54 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 54 + config :statusphere, StatusphereWeb.Endpoint, 55 55 url: [host: host, port: 443, scheme: "https"], 56 56 http: [ 57 57 # Enable IPv6 and bind on all interfaces. ··· 67 67 # To get SSL working, you will need to add the `https` key 68 68 # to your endpoint configuration: 69 69 # 70 - # config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 70 + # config :statusphere, StatusphereWeb.Endpoint, 71 71 # https: [ 72 72 # ..., 73 73 # port: 443, ··· 89 89 # We also recommend setting `force_ssl` in your config/prod.exs, 90 90 # ensuring no data is ever sent via http, always redirecting to https: 91 91 # 92 - # config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 92 + # config :statusphere, StatusphereWeb.Endpoint, 93 93 # force_ssl: [hsts: true] 94 94 # 95 95 # Check `Plug.SSL` for all available options in `force_ssl`.
+3 -3
config/test.exs
··· 5 5 # The MIX_TEST_PARTITION environment variable can be used 6 6 # to provide built-in test partitioning in CI environment. 7 7 # Run `mix help test` for more information. 8 - config :statusphere_elixir, StatusphereElixir.Repo, 9 - database: Path.expand("../statusphere_elixir_test.db", __DIR__), 8 + config :statusphere, Statusphere.Repo, 9 + database: Path.expand("../statusphere_test.db", __DIR__), 10 10 pool_size: 5, 11 11 pool: Ecto.Adapters.SQL.Sandbox 12 12 13 13 # We don't run a server during test. If one is required, 14 14 # you can enable the server option below. 15 - config :statusphere_elixir, StatusphereElixirWeb.Endpoint, 15 + config :statusphere, StatusphereWeb.Endpoint, 16 16 http: [ip: {127, 0, 0, 1}, port: 4002], 17 17 secret_key_base: "AjDaXXlcrR04FEL+g7EV1+pKX7Fnvuhp63uWWK4I8zwKYmgReKy4WxqvdSNDdoT7", 18 18 server: false
+41
lib/statusphere/application.ex
··· 1 + defmodule Statusphere.Application do 2 + # See https://hexdocs.pm/elixir/Application.html 3 + # for more information on OTP Applications 4 + @moduledoc false 5 + 6 + use Application 7 + 8 + @impl true 9 + def start(_type, _args) do 10 + children = [ 11 + StatusphereWeb.Telemetry, 12 + Statusphere.Repo, 13 + {Ecto.Migrator, 14 + repos: Application.fetch_env!(:statusphere, :ecto_repos), skip: skip_migrations?()}, 15 + {DNSCluster, query: Application.get_env(:statusphere, :dns_cluster_query) || :ignore}, 16 + {Phoenix.PubSub, name: Statusphere.PubSub}, 17 + # Start a worker by calling: Statusphere.Worker.start_link(arg) 18 + # {Statusphere.Worker, arg}, 19 + # Start to serve requests, typically the last entry 20 + StatusphereWeb.Endpoint 21 + ] 22 + 23 + # See https://hexdocs.pm/elixir/Supervisor.html 24 + # for other strategies and supported options 25 + opts = [strategy: :one_for_one, name: Statusphere.Supervisor] 26 + Supervisor.start_link(children, opts) 27 + end 28 + 29 + # Tell Phoenix to update the endpoint configuration 30 + # whenever the application is updated. 31 + @impl true 32 + def config_change(changed, _new, removed) do 33 + StatusphereWeb.Endpoint.config_change(changed, removed) 34 + :ok 35 + end 36 + 37 + defp skip_migrations?() do 38 + # By default, sqlite migrations are run when using a release 39 + System.get_env("RELEASE_NAME") == nil 40 + end 41 + end
+5
lib/statusphere/repo.ex
··· 1 + defmodule Statusphere.Repo do 2 + use Ecto.Repo, 3 + otp_app: :statusphere, 4 + adapter: Ecto.Adapters.SQLite3 5 + end
+2 -2
lib/statusphere_elixir.ex lib/statusphere.ex
··· 1 - defmodule StatusphereElixir do 1 + defmodule Statusphere do 2 2 @moduledoc """ 3 - StatusphereElixir keeps the contexts that define your domain 3 + Statusphere keeps the contexts that define your domain 4 4 and business logic. 5 5 6 6 Contexts are also responsible for managing your data, regardless
-41
lib/statusphere_elixir/application.ex
··· 1 - defmodule StatusphereElixir.Application do 2 - # See https://hexdocs.pm/elixir/Application.html 3 - # for more information on OTP Applications 4 - @moduledoc false 5 - 6 - use Application 7 - 8 - @impl true 9 - def start(_type, _args) do 10 - children = [ 11 - StatusphereElixirWeb.Telemetry, 12 - StatusphereElixir.Repo, 13 - {Ecto.Migrator, 14 - repos: Application.fetch_env!(:statusphere_elixir, :ecto_repos), skip: skip_migrations?()}, 15 - {DNSCluster, query: Application.get_env(:statusphere_elixir, :dns_cluster_query) || :ignore}, 16 - {Phoenix.PubSub, name: StatusphereElixir.PubSub}, 17 - # Start a worker by calling: StatusphereElixir.Worker.start_link(arg) 18 - # {StatusphereElixir.Worker, arg}, 19 - # Start to serve requests, typically the last entry 20 - StatusphereElixirWeb.Endpoint 21 - ] 22 - 23 - # See https://hexdocs.pm/elixir/Supervisor.html 24 - # for other strategies and supported options 25 - opts = [strategy: :one_for_one, name: StatusphereElixir.Supervisor] 26 - Supervisor.start_link(children, opts) 27 - end 28 - 29 - # Tell Phoenix to update the endpoint configuration 30 - # whenever the application is updated. 31 - @impl true 32 - def config_change(changed, _new, removed) do 33 - StatusphereElixirWeb.Endpoint.config_change(changed, removed) 34 - :ok 35 - end 36 - 37 - defp skip_migrations?() do 38 - # By default, sqlite migrations are run when using a release 39 - System.get_env("RELEASE_NAME") == nil 40 - end 41 - end
-5
lib/statusphere_elixir/repo.ex
··· 1 - defmodule StatusphereElixir.Repo do 2 - use Ecto.Repo, 3 - otp_app: :statusphere_elixir, 4 - adapter: Ecto.Adapters.SQLite3 5 - end
+8 -8
lib/statusphere_elixir_web.ex lib/statusphere_web.ex
··· 1 - defmodule StatusphereElixirWeb do 1 + defmodule StatusphereWeb do 2 2 @moduledoc """ 3 3 The entrypoint for defining your web interface, such 4 4 as controllers, components, channels, and so on. 5 5 6 6 This can be used in your application as: 7 7 8 - use StatusphereElixirWeb, :controller 9 - use StatusphereElixirWeb, :html 8 + use StatusphereWeb, :controller 9 + use StatusphereWeb, :html 10 10 11 11 The definitions below will be executed for every controller, 12 12 component, etc, so keep them short and clean, focused ··· 80 80 # HTML escaping functionality 81 81 import Phoenix.HTML 82 82 # Core UI components 83 - import StatusphereElixirWeb.CoreComponents 83 + import StatusphereWeb.CoreComponents 84 84 85 85 # Common modules used in templates 86 86 alias Phoenix.LiveView.JS 87 - alias StatusphereElixirWeb.Layouts 87 + alias StatusphereWeb.Layouts 88 88 89 89 # Routes generation with the ~p sigil 90 90 unquote(verified_routes()) ··· 94 94 def verified_routes do 95 95 quote do 96 96 use Phoenix.VerifiedRoutes, 97 - endpoint: StatusphereElixirWeb.Endpoint, 98 - router: StatusphereElixirWeb.Router, 99 - statics: StatusphereElixirWeb.static_paths() 97 + endpoint: StatusphereWeb.Endpoint, 98 + router: StatusphereWeb.Router, 99 + statics: StatusphereWeb.static_paths() 100 100 end 101 101 end 102 102
+3 -3
lib/statusphere_elixir_web/components/core_components.ex lib/statusphere_web/components/core_components.ex
··· 1 - defmodule StatusphereElixirWeb.CoreComponents do 1 + defmodule StatusphereWeb.CoreComponents do 2 2 @moduledoc """ 3 3 Provides core UI components. 4 4 ··· 475 475 # uncommenting and adjusting the following code: 476 476 477 477 # if count = opts[:count] do 478 - # Gettext.dngettext(StatusphereElixirWeb.Gettext, "errors", msg, msg, count, opts) 478 + # Gettext.dngettext(StatusphereWeb.Gettext, "errors", msg, msg, count, opts) 479 479 # else 480 - # Gettext.dgettext(StatusphereElixirWeb.Gettext, "errors", msg, opts) 480 + # Gettext.dgettext(StatusphereWeb.Gettext, "errors", msg, opts) 481 481 # end 482 482 483 483 Enum.reduce(opts, msg, fn {key, value}, acc ->
+2 -2
lib/statusphere_elixir_web/components/layouts.ex lib/statusphere_web/components/layouts.ex
··· 1 - defmodule StatusphereElixirWeb.Layouts do 1 + defmodule StatusphereWeb.Layouts do 2 2 @moduledoc """ 3 3 This module holds layouts and related functionality 4 4 used by your application. 5 5 """ 6 - use StatusphereElixirWeb, :html 6 + use StatusphereWeb, :html 7 7 8 8 # Embed all files in layouts/* within this module. 9 9 # The default root.html.heex file contains the HTML
+1 -1
lib/statusphere_elixir_web/components/layouts/root.html.heex lib/statusphere_web/components/layouts/root.html.heex
··· 4 4 <meta charset="utf-8" /> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 6 <meta name="csrf-token" content={get_csrf_token()} /> 7 - <.live_title default="StatusphereElixir" suffix=" · Phoenix Framework"> 7 + <.live_title default="Statusphere" suffix=" · Phoenix Framework"> 8 8 {assigns[:page_title]} 9 9 </.live_title> 10 10 <link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
+4 -4
lib/statusphere_elixir_web/controllers/error_html.ex lib/statusphere_web/controllers/error_html.ex
··· 1 - defmodule StatusphereElixirWeb.ErrorHTML do 1 + defmodule StatusphereWeb.ErrorHTML do 2 2 @moduledoc """ 3 3 This module is invoked by your endpoint in case of errors on HTML requests. 4 4 5 5 See config/config.exs. 6 6 """ 7 - use StatusphereElixirWeb, :html 7 + use StatusphereWeb, :html 8 8 9 9 # If you want to customize your error pages, 10 10 # uncomment the embed_templates/1 call below 11 11 # and add pages to the error directory: 12 12 # 13 - # * lib/statusphere_elixir_web/controllers/error_html/404.html.heex 14 - # * lib/statusphere_elixir_web/controllers/error_html/500.html.heex 13 + # * lib/statusphere_web/controllers/error_html/404.html.heex 14 + # * lib/statusphere_web/controllers/error_html/500.html.heex 15 15 # 16 16 # embed_templates "error_html/*" 17 17
+1 -1
lib/statusphere_elixir_web/controllers/error_json.ex lib/statusphere_web/controllers/error_json.ex
··· 1 - defmodule StatusphereElixirWeb.ErrorJSON do 1 + defmodule StatusphereWeb.ErrorJSON do 2 2 @moduledoc """ 3 3 This module is invoked by your endpoint in case of errors on JSON requests. 4 4
-7
lib/statusphere_elixir_web/controllers/page_controller.ex
··· 1 - defmodule StatusphereElixirWeb.PageController do 2 - use StatusphereElixirWeb, :controller 3 - 4 - def home(conn, _params) do 5 - render(conn, :home) 6 - end 7 - end
+2 -2
lib/statusphere_elixir_web/controllers/page_html.ex lib/statusphere_web/controllers/page_html.ex
··· 1 - defmodule StatusphereElixirWeb.PageHTML do 1 + defmodule StatusphereWeb.PageHTML do 2 2 @moduledoc """ 3 3 This module contains pages rendered by PageController. 4 4 5 5 See the `page_html` directory for all templates available. 6 6 """ 7 - use StatusphereElixirWeb, :html 7 + use StatusphereWeb, :html 8 8 9 9 embed_templates "page_html/*" 10 10 end
-202
lib/statusphere_elixir_web/controllers/page_html/home.html.heex
··· 1 - <Layouts.flash_group flash={@flash} /> 2 - <div class="left-[40rem] fixed inset-y-0 right-0 z-0 hidden lg:block xl:left-[50rem]"> 3 - <svg 4 - viewBox="0 0 1480 957" 5 - fill="none" 6 - aria-hidden="true" 7 - class="absolute inset-0 h-full w-full" 8 - preserveAspectRatio="xMinYMid slice" 9 - > 10 - <path fill="#EE7868" d="M0 0h1480v957H0z" /> 11 - <path 12 - d="M137.542 466.27c-582.851-48.41-988.806-82.127-1608.412 658.2l67.39 810 3083.15-256.51L1535.94-49.622l-98.36 8.183C1269.29 281.468 734.115 515.799 146.47 467.012l-8.928-.742Z" 13 - fill="#FF9F92" 14 - /> 15 - <path 16 - d="M371.028 528.664C-169.369 304.988-545.754 149.198-1361.45 665.565l-182.58 792.025 3014.73 694.98 389.42-1689.25-96.18-22.171C1505.28 697.438 924.153 757.586 379.305 532.09l-8.277-3.426Z" 17 - fill="#FA8372" 18 - /> 19 - <path 20 - d="M359.326 571.714C-104.765 215.795-428.003-32.102-1349.55 255.554l-282.3 1224.596 3047.04 722.01 312.24-1354.467C1411.25 1028.3 834.355 935.995 366.435 577.166l-7.109-5.452Z" 21 - fill="#E96856" 22 - fill-opacity=".6" 23 - /> 24 - <path 25 - d="M1593.87 1236.88c-352.15 92.63-885.498-145.85-1244.602-613.557l-5.455-7.105C-12.347 152.31-260.41-170.8-1225-131.458l-368.63 1599.048 3057.19 704.76 130.31-935.47Z" 26 - fill="#C42652" 27 - fill-opacity=".2" 28 - /> 29 - <path 30 - d="M1411.91 1526.93c-363.79 15.71-834.312-330.6-1085.883-863.909l-3.822-8.102C72.704 125.95-101.074-242.476-1052.01-408.907l-699.85 1484.267 2837.75 1338.01 326.02-886.44Z" 31 - fill="#A41C42" 32 - fill-opacity=".2" 33 - /> 34 - <path 35 - d="M1116.26 1863.69c-355.457-78.98-720.318-535.27-825.287-1115.521l-1.594-8.816C185.286 163.833 112.786-237.016-762.678-643.898L-1822.83 608.665 571.922 2635.55l544.338-771.86Z" 36 - fill="#A41C42" 37 - fill-opacity=".2" 38 - /> 39 - </svg> 40 - </div> 41 - <div class="px-4 py-10 sm:px-6 sm:py-28 lg:px-8 xl:px-28 xl:py-32"> 42 - <div class="mx-auto max-w-xl lg:mx-0"> 43 - <svg viewBox="0 0 71 48" class="h-12" aria-hidden="true"> 44 - <path 45 - d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z" 46 - fill="#FD4F00" 47 - /> 48 - </svg> 49 - <div class="mt-10 flex justify-between items-center"> 50 - <h1 class="flex items-center text-sm font-semibold leading-6"> 51 - Phoenix Framework 52 - <small class="badge badge-warning badge-sm ml-3"> 53 - v{Application.spec(:phoenix, :vsn)} 54 - </small> 55 - </h1> 56 - <Layouts.theme_toggle /> 57 - </div> 58 - 59 - <p class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-balance"> 60 - Peace of mind from prototype to production. 61 - </p> 62 - <p class="mt-4 leading-7 text-base-content/70"> 63 - Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale. 64 - </p> 65 - <div class="flex"> 66 - <div class="w-full sm:w-auto"> 67 - <div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-3"> 68 - <a 69 - href="https://hexdocs.pm/phoenix/overview.html" 70 - class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6" 71 - > 72 - <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"> 73 - </span> 74 - <span class="relative flex items-center gap-4 sm:flex-col"> 75 - <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6"> 76 - <path d="m12 4 10-2v18l-10 2V4Z" fill="currentColor" fill-opacity=".15" /> 77 - <path 78 - d="M12 4 2 2v18l10 2m0-18v18m0-18 10-2v18l-10 2" 79 - stroke="currentColor" 80 - stroke-width="2" 81 - stroke-linecap="round" 82 - stroke-linejoin="round" 83 - /> 84 - </svg> 85 - Guides &amp; Docs 86 - </span> 87 - </a> 88 - <a 89 - href="https://github.com/phoenixframework/phoenix" 90 - class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6" 91 - > 92 - <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"> 93 - </span> 94 - <span class="relative flex items-center gap-4 sm:flex-col"> 95 - <svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6"> 96 - <path 97 - fill="currentColor" 98 - fill-rule="evenodd" 99 - clip-rule="evenodd" 100 - d="M12 0C5.37 0 0 5.506 0 12.303c0 5.445 3.435 10.043 8.205 11.674.6.107.825-.262.825-.585 0-.292-.015-1.261-.015-2.291C6 21.67 5.22 20.346 4.98 19.654c-.135-.354-.72-1.446-1.23-1.738-.42-.23-1.02-.8-.015-.815.945-.015 1.62.892 1.845 1.261 1.08 1.86 2.805 1.338 3.495 1.015.105-.8.42-1.338.765-1.645-2.67-.308-5.46-1.37-5.46-6.075 0-1.338.465-2.446 1.23-3.307-.12-.308-.54-1.569.12-3.26 0 0 1.005-.323 3.3 1.26.96-.276 1.98-.415 3-.415s2.04.139 3 .416c2.295-1.6 3.3-1.261 3.3-1.261.66 1.691.24 2.952.12 3.26.765.861 1.23 1.953 1.23 3.307 0 4.721-2.805 5.767-5.475 6.075.435.384.81 1.122.81 2.276 0 1.645-.015 2.968-.015 3.383 0 .323.225.707.825.585a12.047 12.047 0 0 0 5.919-4.489A12.536 12.536 0 0 0 24 12.304C24 5.505 18.63 0 12 0Z" 101 - /> 102 - </svg> 103 - Source Code 104 - </span> 105 - </a> 106 - <a 107 - href={"https://github.com/phoenixframework/phoenix/blob/v#{Application.spec(:phoenix, :vsn)}/CHANGELOG.md"} 108 - class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6" 109 - > 110 - <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"> 111 - </span> 112 - <span class="relative flex items-center gap-4 sm:flex-col"> 113 - <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6"> 114 - <path 115 - d="M12 1v6M12 17v6" 116 - stroke="currentColor" 117 - stroke-width="2" 118 - stroke-linecap="round" 119 - stroke-linejoin="round" 120 - /> 121 - <circle 122 - cx="12" 123 - cy="12" 124 - r="4" 125 - fill="currentColor" 126 - fill-opacity=".15" 127 - stroke="currentColor" 128 - stroke-width="2" 129 - stroke-linecap="round" 130 - stroke-linejoin="round" 131 - /> 132 - </svg> 133 - Changelog 134 - </span> 135 - </a> 136 - </div> 137 - <div class="mt-10 grid grid-cols-1 gap-y-4 text-sm leading-6 text-base-content/80 sm:grid-cols-2"> 138 - <div> 139 - <a 140 - href="https://elixirforum.com" 141 - class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content" 142 - > 143 - <svg 144 - viewBox="0 0 16 16" 145 - aria-hidden="true" 146 - class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content" 147 - > 148 - <path d="M8 13.833c3.866 0 7-2.873 7-6.416C15 3.873 11.866 1 8 1S1 3.873 1 7.417c0 1.081.292 2.1.808 2.995.606 1.05.806 2.399.086 3.375l-.208.283c-.285.386-.01.905.465.85.852-.098 2.048-.318 3.137-.81a3.717 3.717 0 0 1 1.91-.318c.263.027.53.041.802.041Z" /> 149 - </svg> 150 - Discuss on the Elixir Forum 151 - </a> 152 - </div> 153 - <div> 154 - <a 155 - href="https://discord.gg/elixir" 156 - class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content" 157 - > 158 - <svg 159 - viewBox="0 0 16 16" 160 - aria-hidden="true" 161 - class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content" 162 - > 163 - <path d="M13.545 2.995c-1.02-.46-2.114-.8-3.257-.994a.05.05 0 0 0-.052.024c-.141.246-.297.567-.406.82a12.377 12.377 0 0 0-3.658 0 8.238 8.238 0 0 0-.412-.82.052.052 0 0 0-.052-.024 13.315 13.315 0 0 0-3.257.994.046.046 0 0 0-.021.018C.356 6.063-.213 9.036.066 11.973c.001.015.01.029.02.038a13.353 13.353 0 0 0 3.996 1.987.052.052 0 0 0 .056-.018c.308-.414.582-.85.818-1.309a.05.05 0 0 0-.028-.069 8.808 8.808 0 0 1-1.248-.585.05.05 0 0 1-.005-.084c.084-.062.168-.126.248-.191a.05.05 0 0 1 .051-.007c2.619 1.176 5.454 1.176 8.041 0a.05.05 0 0 1 .053.006c.08.065.164.13.248.192a.05.05 0 0 1-.004.084c-.399.23-.813.423-1.249.585a.05.05 0 0 0-.027.07c.24.457.514.893.817 1.307a.051.051 0 0 0 .056.019 13.31 13.31 0 0 0 4.001-1.987.05.05 0 0 0 .021-.037c.334-3.396-.559-6.345-2.365-8.96a.04.04 0 0 0-.021-.02Zm-8.198 7.19c-.789 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.637 1.587-1.438 1.587Zm5.316 0c-.788 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.63 1.587-1.438 1.587Z" /> 164 - </svg> 165 - Join our Discord server 166 - </a> 167 - </div> 168 - <div> 169 - <a 170 - href="https://elixir-slack.community/" 171 - class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content" 172 - > 173 - <svg 174 - viewBox="0 0 16 16" 175 - aria-hidden="true" 176 - class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content" 177 - > 178 - <path d="M3.361 10.11a1.68 1.68 0 1 1-1.68-1.681h1.68v1.682ZM4.209 10.11a1.68 1.68 0 1 1 3.361 0v4.21a1.68 1.68 0 1 1-3.361 0v-4.21ZM5.89 3.361a1.68 1.68 0 1 1 1.681-1.68v1.68H5.89ZM5.89 4.209a1.68 1.68 0 1 1 0 3.361H1.68a1.68 1.68 0 1 1 0-3.361h4.21ZM12.639 5.89a1.68 1.68 0 1 1 1.68 1.681h-1.68V5.89ZM11.791 5.89a1.68 1.68 0 1 1-3.361 0V1.68a1.68 1.68 0 0 1 3.361 0v4.21ZM10.11 12.639a1.68 1.68 0 1 1-1.681 1.68v-1.68h1.682ZM10.11 11.791a1.68 1.68 0 1 1 0-3.361h4.21a1.68 1.68 0 1 1 0 3.361h-4.21Z" /> 179 - </svg> 180 - Join us on Slack 181 - </a> 182 - </div> 183 - <div> 184 - <a 185 - href="https://fly.io/docs/elixir/getting-started/" 186 - class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content" 187 - > 188 - <svg 189 - viewBox="0 0 20 20" 190 - aria-hidden="true" 191 - class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content" 192 - > 193 - <path d="M1 12.5A4.5 4.5 0 005.5 17H15a4 4 0 001.866-7.539 3.504 3.504 0 00-4.504-4.272A4.5 4.5 0 004.06 8.235 4.502 4.502 0 001 12.5z" /> 194 - </svg> 195 - Deploy your application 196 - </a> 197 - </div> 198 - </div> 199 - </div> 200 - </div> 201 - </div> 202 - </div>
+7 -7
lib/statusphere_elixir_web/endpoint.ex lib/statusphere_web/endpoint.ex
··· 1 - defmodule StatusphereElixirWeb.Endpoint do 2 - use Phoenix.Endpoint, otp_app: :statusphere_elixir 1 + defmodule StatusphereWeb.Endpoint do 2 + use Phoenix.Endpoint, otp_app: :statusphere 3 3 4 4 # The session will be stored in the cookie and signed, 5 5 # this means its contents can be read but not tampered with. 6 6 # Set :encryption_salt if you would also like to encrypt it. 7 7 @session_options [ 8 8 store: :cookie, 9 - key: "_statusphere_elixir_key", 9 + key: "_statusphere_key", 10 10 signing_salt: "zbKtWcZI", 11 11 same_site: "Lax" 12 12 ] ··· 22 22 # static files generated by running `phx.digest`. 23 23 plug Plug.Static, 24 24 at: "/", 25 - from: :statusphere_elixir, 25 + from: :statusphere, 26 26 gzip: not code_reloading?, 27 - only: StatusphereElixirWeb.static_paths(), 27 + only: StatusphereWeb.static_paths(), 28 28 raise_on_missing_only: code_reloading? 29 29 30 30 # Code reloading can be explicitly enabled under the ··· 33 33 socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket 34 34 plug Phoenix.LiveReloader 35 35 plug Phoenix.CodeReloader 36 - plug Phoenix.Ecto.CheckRepoStatus, otp_app: :statusphere_elixir 36 + plug Phoenix.Ecto.CheckRepoStatus, otp_app: :statusphere 37 37 end 38 38 39 39 plug Phoenix.LiveDashboard.RequestLogger, ··· 51 51 plug Plug.MethodOverride 52 52 plug Plug.Head 53 53 plug Plug.Session, @session_options 54 - plug StatusphereElixirWeb.Router 54 + plug StatusphereWeb.Router 55 55 end
+13 -7
lib/statusphere_elixir_web/router.ex lib/statusphere_web/router.ex
··· 1 - defmodule StatusphereElixirWeb.Router do 2 - use StatusphereElixirWeb, :router 1 + defmodule StatusphereWeb.Router do 2 + use StatusphereWeb, :router 3 3 4 4 pipeline :browser do 5 5 plug :accepts, ["html"] 6 6 plug :fetch_session 7 7 plug :fetch_live_flash 8 - plug :put_root_layout, html: {StatusphereElixirWeb.Layouts, :root} 8 + plug :put_root_layout, html: {StatusphereWeb.Layouts, :root} 9 9 plug :protect_from_forgery 10 10 plug :put_secure_browser_headers 11 11 end ··· 14 14 plug :accepts, ["json"] 15 15 end 16 16 17 - scope "/", StatusphereElixirWeb do 17 + scope "/", StatusphereWeb do 18 18 pipe_through :browser 19 19 20 20 get "/", PageController, :home 21 21 end 22 + 23 + forward "/oauth", Atex.OAuth.Plug, callback: {__MODULE__, :oauth_callback, []} 22 24 23 25 # Other scopes may use custom stacks. 24 - # scope "/api", StatusphereElixirWeb do 26 + # scope "/api", StatusphereWeb do 25 27 # pipe_through :api 26 28 # end 27 29 28 30 # Enable LiveDashboard in development 29 - if Application.compile_env(:statusphere_elixir, :dev_routes) do 31 + if Application.compile_env(:statusphere, :dev_routes) do 30 32 # If you want to use the LiveDashboard in production, you should put 31 33 # it behind authentication and allow only admins to access it. 32 34 # If your application does not have an admins-only section yet, ··· 37 39 scope "/dev" do 38 40 pipe_through :browser 39 41 40 - live_dashboard "/dashboard", metrics: StatusphereElixirWeb.Telemetry 42 + live_dashboard "/dashboard", metrics: StatusphereWeb.Telemetry 41 43 end 44 + end 45 + 46 + def oauth_callback(conn) do 47 + redirect(conn, to: "/") 42 48 end 43 49 end
+7 -7
lib/statusphere_elixir_web/telemetry.ex lib/statusphere_web/telemetry.ex
··· 1 - defmodule StatusphereElixirWeb.Telemetry do 1 + defmodule StatusphereWeb.Telemetry do 2 2 use Supervisor 3 3 import Telemetry.Metrics 4 4 ··· 53 53 ), 54 54 55 55 # Database Metrics 56 - summary("statusphere_elixir.repo.query.total_time", 56 + summary("statusphere.repo.query.total_time", 57 57 unit: {:native, :millisecond}, 58 58 description: "The sum of the other measurements" 59 59 ), 60 - summary("statusphere_elixir.repo.query.decode_time", 60 + summary("statusphere.repo.query.decode_time", 61 61 unit: {:native, :millisecond}, 62 62 description: "The time spent decoding the data received from the database" 63 63 ), 64 - summary("statusphere_elixir.repo.query.query_time", 64 + summary("statusphere.repo.query.query_time", 65 65 unit: {:native, :millisecond}, 66 66 description: "The time spent executing the query" 67 67 ), 68 - summary("statusphere_elixir.repo.query.queue_time", 68 + summary("statusphere.repo.query.queue_time", 69 69 unit: {:native, :millisecond}, 70 70 description: "The time spent waiting for a database connection" 71 71 ), 72 - summary("statusphere_elixir.repo.query.idle_time", 72 + summary("statusphere.repo.query.idle_time", 73 73 unit: {:native, :millisecond}, 74 74 description: 75 75 "The time the connection spent waiting before being checked out for the query" ··· 87 87 [ 88 88 # A module, function and arguments to be invoked periodically. 89 89 # This function must call :telemetry.execute/3 and a metric must be added above. 90 - # {StatusphereElixirWeb, :count_users, []} 90 + # {StatusphereWeb, :count_users, []} 91 91 ] 92 92 end 93 93 end
+7
lib/statusphere_web/controllers/page_controller.ex
··· 1 + defmodule StatusphereWeb.PageController do 2 + use StatusphereWeb, :controller 3 + 4 + def home(conn, _params) do 5 + render(conn, :home) 6 + end 7 + end
+3
lib/statusphere_web/controllers/page_html/home.html.heex
··· 1 + <Layouts.app flash={@flash}> 2 + <div>hello</div> 3 + </Layouts.app>
+9 -7
mix.exs
··· 1 - defmodule StatusphereElixir.MixProject do 1 + defmodule Statusphere.MixProject do 2 2 use Mix.Project 3 3 4 4 def project do 5 5 [ 6 - app: :statusphere_elixir, 6 + app: :statusphere, 7 7 version: "0.1.0", 8 8 elixir: "~> 1.15", 9 9 elixirc_paths: elixirc_paths(Mix.env()), ··· 20 20 # Type `mix help compile.app` for more information. 21 21 def application do 22 22 [ 23 - mod: {StatusphereElixir.Application, []}, 23 + mod: {Statusphere.Application, []}, 24 24 extra_applications: [:logger, :runtime_tools] 25 25 ] 26 26 end ··· 63 63 {:jason, "~> 1.2"}, 64 64 {:dns_cluster, "~> 0.2.0"}, 65 65 {:bandit, "~> 1.5"}, 66 - {:atex, "~> 0.6"}, 66 + # {:atex, "~> 0.6"}, 67 + {:atex, 68 + git: "https://github.com/cometsh/atex.git", ref: "2cc3686d47e30118ac8ac2d48cdc135a13da9163"}, 67 69 {:drinkup, "~> 0.1"}, 68 70 {:typedstruct, "~> 0.5"} 69 71 ] ··· 85 87 # "tailwind.install --if-missing", 86 88 "esbuild.install --if-missing" 87 89 ], 88 - "assets.build": ["compile", "tailwind statusphere_elixir", "esbuild statusphere_elixir"], 90 + "assets.build": ["compile", "tailwind statusphere", "esbuild statusphere"], 89 91 "assets.deploy": [ 90 - "tailwind statusphere_elixir --minify", 91 - "esbuild statusphere_elixir --minify", 92 + "tailwind statusphere --minify", 93 + "esbuild statusphere --minify", 92 94 "phx.digest" 93 95 ], 94 96 precommit: ["compile --warnings-as-errors", "deps.unlock --unused", "format", "test"]
+1 -1
mix.lock
··· 1 1 %{ 2 - "atex": {:hex, :atex, "0.6.0", "a02f3c1b3ef04d8cd30243a05fc3629929c66d826e1d6a7e9d4ec6076ac89aea", [:mix], [{:ex_cldr, "~> 2.42", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.11", [hex: :jose, repo: "hexpm", optional: false]}, {:multiformats_ex, "~> 0.2", [hex: :multiformats_ex, repo: "hexpm", optional: false]}, {:peri, "~> 0.6", [hex: :peri, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:recase, "~> 0.5", [hex: :recase, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:typedstruct, "~> 0.5", [hex: :typedstruct, repo: "hexpm", optional: false]}], "hexpm", "a3615e361e1e1b2887910834b3ede88680a02e4d585243ea90d0a6394f688aa2"}, 2 + "atex": {:git, "https://github.com/cometsh/atex.git", "2cc3686d47e30118ac8ac2d48cdc135a13da9163", [ref: "2cc3686d47e30118ac8ac2d48cdc135a13da9163"]}, 3 3 "bandit": {:hex, :bandit, "1.9.0", "6dc1ff2c30948dfecf32db574cc3447c7b9d70e0b61140098df3818870b01b76", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "2538aaa1663b40ca9cbd8ca1f8a540cb49e5baf34c6ffef068369cc45f9146f2"}, 4 4 "car": {:hex, :car, "0.1.1", "a5bc4c5c1be96eab437634b3c0ccad1fe17b5e3d68c22a4031241ae1345aebd4", [:mix], [{:cbor, "~> 1.0.0", [hex: :cbor, repo: "hexpm", optional: false]}, {:typedstruct, "~> 0.5", [hex: :typedstruct, repo: "hexpm", optional: false]}, {:varint, "~> 1.4", [hex: :varint, repo: "hexpm", optional: false]}], "hexpm", "f895dda8123d04dd336db5a2bf0d0b47f4559cd5383f83fcca0700c1b45bfb6a"}, 5 5 "cbor": {:hex, :cbor, "1.0.1", "39511158e8ea5a57c1fcb9639aaa7efde67129678fee49ebbda780f6f24959b0", [:mix], [], "hexpm", "5431acbe7a7908f17f6a9cd43311002836a34a8ab01876918d8cfb709cd8b6a2"},
+1 -1
priv/repo/seeds.exs
··· 5 5 # Inside the script, you can read and write to any of your 6 6 # repositories directly: 7 7 # 8 - # StatusphereElixir.Repo.insert!(%StatusphereElixir.SomeSchema{}) 8 + # Statusphere.Repo.insert!(%Statusphere.SomeSchema{}) 9 9 # 10 10 # We recommend using the bang functions (`insert!`, `update!` 11 11 # and so on) as they will fail if something goes wrong.
+5 -4
test/statusphere_elixir_web/controllers/error_html_test.exs
··· 1 - defmodule StatusphereElixirWeb.ErrorHTMLTest do 2 - use StatusphereElixirWeb.ConnCase, async: true 1 + defmodule StatusphereWeb.ErrorHTMLTest do 2 + use StatusphereWeb.ConnCase, async: true 3 3 4 4 # Bring render_to_string/4 for testing custom views 5 5 import Phoenix.Template, only: [render_to_string: 4] 6 6 7 7 test "renders 404.html" do 8 - assert render_to_string(StatusphereElixirWeb.ErrorHTML, "404", "html", []) == "Not Found" 8 + assert render_to_string(StatusphereWeb.ErrorHTML, "404", "html", []) == "Not Found" 9 9 end 10 10 11 11 test "renders 500.html" do 12 - assert render_to_string(StatusphereElixirWeb.ErrorHTML, "500", "html", []) == "Internal Server Error" 12 + assert render_to_string(StatusphereWeb.ErrorHTML, "500", "html", []) == 13 + "Internal Server Error" 13 14 end 14 15 end
+4 -4
test/statusphere_elixir_web/controllers/error_json_test.exs
··· 1 - defmodule StatusphereElixirWeb.ErrorJSONTest do 2 - use StatusphereElixirWeb.ConnCase, async: true 1 + defmodule StatusphereWeb.ErrorJSONTest do 2 + use StatusphereWeb.ConnCase, async: true 3 3 4 4 test "renders 404" do 5 - assert StatusphereElixirWeb.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}} 5 + assert StatusphereWeb.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}} 6 6 end 7 7 8 8 test "renders 500" do 9 - assert StatusphereElixirWeb.ErrorJSON.render("500.json", %{}) == 9 + assert StatusphereWeb.ErrorJSON.render("500.json", %{}) == 10 10 %{errors: %{detail: "Internal Server Error"}} 11 11 end 12 12 end
+2 -2
test/statusphere_elixir_web/controllers/page_controller_test.exs
··· 1 - defmodule StatusphereElixirWeb.PageControllerTest do 2 - use StatusphereElixirWeb.ConnCase 1 + defmodule StatusphereWeb.PageControllerTest do 2 + use StatusphereWeb.ConnCase 3 3 4 4 test "GET /", %{conn: conn} do 5 5 conn = get(conn, ~p"/")
+6 -6
test/support/conn_case.ex
··· 1 - defmodule StatusphereElixirWeb.ConnCase do 1 + defmodule StatusphereWeb.ConnCase do 2 2 @moduledoc """ 3 3 This module defines the test case to be used by 4 4 tests that require setting up a connection. ··· 11 11 we enable the SQL sandbox, so changes done to the database 12 12 are reverted at the end of every test. If you are using 13 13 PostgreSQL, you can even run database tests asynchronously 14 - by setting `use StatusphereElixirWeb.ConnCase, async: true`, although 14 + by setting `use StatusphereWeb.ConnCase, async: true`, although 15 15 this option is not recommended for other databases. 16 16 """ 17 17 ··· 20 20 using do 21 21 quote do 22 22 # The default endpoint for testing 23 - @endpoint StatusphereElixirWeb.Endpoint 23 + @endpoint StatusphereWeb.Endpoint 24 24 25 - use StatusphereElixirWeb, :verified_routes 25 + use StatusphereWeb, :verified_routes 26 26 27 27 # Import conveniences for testing with connections 28 28 import Plug.Conn 29 29 import Phoenix.ConnTest 30 - import StatusphereElixirWeb.ConnCase 30 + import StatusphereWeb.ConnCase 31 31 end 32 32 end 33 33 34 34 setup tags do 35 - StatusphereElixir.DataCase.setup_sandbox(tags) 35 + Statusphere.DataCase.setup_sandbox(tags) 36 36 {:ok, conn: Phoenix.ConnTest.build_conn()} 37 37 end 38 38 end
+6 -6
test/support/data_case.ex
··· 1 - defmodule StatusphereElixir.DataCase do 1 + defmodule Statusphere.DataCase do 2 2 @moduledoc """ 3 3 This module defines the setup for tests requiring 4 4 access to the application's data layer. ··· 10 10 we enable the SQL sandbox, so changes done to the database 11 11 are reverted at the end of every test. If you are using 12 12 PostgreSQL, you can even run database tests asynchronously 13 - by setting `use StatusphereElixir.DataCase, async: true`, although 13 + by setting `use Statusphere.DataCase, async: true`, although 14 14 this option is not recommended for other databases. 15 15 """ 16 16 ··· 18 18 19 19 using do 20 20 quote do 21 - alias StatusphereElixir.Repo 21 + alias Statusphere.Repo 22 22 23 23 import Ecto 24 24 import Ecto.Changeset 25 25 import Ecto.Query 26 - import StatusphereElixir.DataCase 26 + import Statusphere.DataCase 27 27 end 28 28 end 29 29 30 30 setup tags do 31 - StatusphereElixir.DataCase.setup_sandbox(tags) 31 + Statusphere.DataCase.setup_sandbox(tags) 32 32 :ok 33 33 end 34 34 ··· 36 36 Sets up the sandbox based on the test tags. 37 37 """ 38 38 def setup_sandbox(tags) do 39 - pid = Ecto.Adapters.SQL.Sandbox.start_owner!(StatusphereElixir.Repo, shared: not tags[:async]) 39 + pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Statusphere.Repo, shared: not tags[:async]) 40 40 on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) 41 41 end 42 42
+1 -1
test/test_helper.exs
··· 1 1 ExUnit.start() 2 - Ecto.Adapters.SQL.Sandbox.mode(StatusphereElixir.Repo, :manual) 2 + Ecto.Adapters.SQL.Sandbox.mode(Statusphere.Repo, :manual)