Resources
19 |-
20 |
- 21 | Guides & Docs 22 | 23 |
- 24 | Source 25 | 26 |
- 27 | v1.5 Changelog 28 | 29 |
├── rel ├── plugins │ └── .gitignore ├── env.bat.eex ├── vm.args.eex ├── env.sh.eex ├── vm.args └── config.exs ├── .tool-versions ├── phoenix_static_buildpack.config ├── .dockerignore ├── elixir_buildpack.config ├── assets ├── .babelrc ├── static │ ├── favicon.ico │ ├── images │ │ ├── favicon.ico │ │ ├── phoenix.png │ │ ├── mstile-70x70.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── browserconfig.xml │ │ ├── site.webmanifest │ │ ├── littlechat-favicon.svg │ │ ├── littlechat-favicon-transparent.svg │ │ ├── littlechat-favicon-centered.svg │ │ ├── safari-pinned-tab.svg │ │ └── littlechat-logo.svg │ └── robots.txt ├── package.json ├── css │ ├── variables.scss │ ├── reset.scss │ ├── app.scss │ └── phoenix.css ├── webpack.config.js └── js │ └── app.js ├── priv ├── repo │ ├── migrations │ │ ├── .formatter.exs │ │ ├── 20200618173019_add_active_call_bool_to_rooms.exs │ │ └── 20200605193730_create_rooms.exs │ └── seeds.exs └── gettext │ ├── en │ └── LC_MESSAGES │ │ └── errors.po │ └── errors.pot ├── test ├── test_helper.exs ├── littlechat_web │ ├── live │ │ └── page_live_test.exs │ └── views │ │ ├── layout_view_test.exs │ │ └── error_view_test.exs └── support │ ├── channel_case.ex │ ├── conn_case.ex │ └── data_case.ex ├── lib ├── littlechat │ ├── connected_user.ex │ ├── repo.ex │ ├── organizer.ex │ ├── room.ex │ └── application.ex ├── littlechat_web │ ├── views │ │ ├── layout_view.ex │ │ ├── error_view.ex │ │ └── error_helpers.ex │ ├── presence.ex │ ├── templates │ │ └── layout │ │ │ ├── app.html.eex │ │ │ ├── live.html.leex │ │ │ └── root.html.leex │ ├── controllers │ │ └── page_controller.ex │ ├── stun.ex │ ├── gettext.ex │ ├── router.ex │ ├── live │ │ ├── page_live.ex │ │ ├── page_live.html.leex │ │ └── room │ │ │ ├── new_live.ex │ │ │ └── show_live.ex │ ├── channels │ │ └── user_socket.ex │ ├── endpoint.ex │ └── telemetry.ex ├── littlechat.ex ├── release_tasks.ex └── littlechat_web.ex ├── release ├── .formatter.exs ├── bin └── release ├── Dockerfile ├── .github └── workflows │ └── elixir.yml ├── config ├── test.exs ├── releases.exs ├── config.exs ├── dev.exs └── prod.exs ├── .gitignore ├── LICENSE.md ├── README.md ├── mix.exs └── mix.lock /rel/plugins/.gitignore: -------------------------------------------------------------------------------- 1 | *.* 2 | !*.exs 3 | !.gitignore -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | erlang 23.0.2 2 | elixir 1.10.3-otp-23 3 | -------------------------------------------------------------------------------- /phoenix_static_buildpack.config: -------------------------------------------------------------------------------- 1 | node_version=12.16.3 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | _build 2 | deps 3 | assets/node_modules 4 | test -------------------------------------------------------------------------------- /elixir_buildpack.config: -------------------------------------------------------------------------------- 1 | elixir_version=1.10.3 2 | erlang_version=23.0.2 3 | -------------------------------------------------------------------------------- /assets/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /priv/repo/migrations/.formatter.exs: -------------------------------------------------------------------------------- 1 | [ 2 | import_deps: [:ecto_sql], 3 | inputs: ["*.exs"] 4 | ] 5 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | Ecto.Adapters.SQL.Sandbox.mode(Littlechat.Repo, :manual) 3 | -------------------------------------------------------------------------------- /assets/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/favicon.ico -------------------------------------------------------------------------------- /lib/littlechat/connected_user.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.ConnectedUser do 2 | defstruct uuid: "" 3 | end 4 | -------------------------------------------------------------------------------- /assets/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/favicon.ico -------------------------------------------------------------------------------- /assets/static/images/phoenix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/phoenix.png -------------------------------------------------------------------------------- /lib/littlechat_web/views/layout_view.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.LayoutView do 2 | use LittlechatWeb, :view 3 | end 4 | -------------------------------------------------------------------------------- /assets/static/images/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/mstile-70x70.png -------------------------------------------------------------------------------- /assets/static/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/favicon-16x16.png -------------------------------------------------------------------------------- /assets/static/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/favicon-32x32.png -------------------------------------------------------------------------------- /assets/static/images/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/mstile-144x144.png -------------------------------------------------------------------------------- /assets/static/images/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/mstile-150x150.png -------------------------------------------------------------------------------- /assets/static/images/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/mstile-310x150.png -------------------------------------------------------------------------------- /assets/static/images/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/mstile-310x310.png -------------------------------------------------------------------------------- /assets/static/images/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/apple-touch-icon.png -------------------------------------------------------------------------------- /release: -------------------------------------------------------------------------------- 1 | source .env 2 | MIX_ENV=prod mix compile 3 | npm run deploy --prefix assets 4 | MIX_ENV=prod mix do phx.digest, distillery.release 5 | -------------------------------------------------------------------------------- /assets/static/images/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/android-chrome-192x192.png -------------------------------------------------------------------------------- /assets/static/images/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littlelines/littlechat/HEAD/assets/static/images/android-chrome-512x512.png -------------------------------------------------------------------------------- /lib/littlechat/repo.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.Repo do 2 | use Ecto.Repo, 3 | otp_app: :littlechat, 4 | adapter: Ecto.Adapters.Postgres 5 | end 6 | -------------------------------------------------------------------------------- /test/littlechat_web/live/page_live_test.exs: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.PageLiveTest do 2 | # use LittlechatWeb.ConnCase 3 | 4 | # import Phoenix.LiveViewTest 5 | end 6 | -------------------------------------------------------------------------------- /lib/littlechat_web/presence.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.Presence do 2 | use Phoenix.Presence, 3 | otp_app: :littlechat, 4 | pubsub_server: Littlechat.PubSub 5 | end 6 | -------------------------------------------------------------------------------- /.formatter.exs: -------------------------------------------------------------------------------- 1 | [ 2 | import_deps: [:ecto, :phoenix], 3 | inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"], 4 | subdirectories: ["priv/*/migrations"] 5 | ] 6 | -------------------------------------------------------------------------------- /lib/littlechat_web/templates/layout/app.html.eex: -------------------------------------------------------------------------------- 1 |
<%= get_flash(@conn, :info) %>
2 |<%= get_flash(@conn, :error) %>
3 | <%= @inner_content %> 4 | -------------------------------------------------------------------------------- /assets/static/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /bin/release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MIX_ENV=prod mix deps.get --only prod 4 | MIX_ENV=prod mix compile 5 | MIX_ENV=prod npm run deploy --prefix assets 6 | MIX_ENV=prod mix phx.digest 7 | source .env 8 | MIX_ENV=prod mix distillery.release --upgrade 9 | -------------------------------------------------------------------------------- /lib/littlechat_web/controllers/page_controller.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.PageController do 2 | use LittlechatWeb, :controller 3 | 4 | def index(conn, _) do 5 | conn 6 | |> redirect(to: Routes.room_new_path(conn, :new)) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/littlechat/organizer.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.Organizer do 2 | alias Littlechat.Repo 3 | alias Littlechat.Room 4 | 5 | import Ecto.Query 6 | 7 | def get_room(slug) when is_binary(slug) do 8 | from(room in Room, where: room.slug == ^slug) 9 | |> Repo.one() 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /priv/repo/migrations/20200618173019_add_active_call_bool_to_rooms.exs: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.Repo.Migrations.AddActiveCallBoolToRooms do 2 | use Ecto.Migration 3 | 4 | def change do 5 | alter table("rooms") do 6 | add :active_call, :boolean, default: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/littlechat.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat do 2 | @moduledoc """ 3 | Littlechat keeps the contexts that define your domain 4 | and business logic. 5 | 6 | Contexts are also responsible for managing your data, regardless 7 | if it comes from the database, an external API or others. 8 | """ 9 | end 10 | -------------------------------------------------------------------------------- /assets/static/images/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 |<%= live_flash(@flash, :info) %>
4 | 5 |<%= live_flash(@flash, :error) %>
8 | 9 | <%= @inner_content %> 10 | 11 | 14 | -------------------------------------------------------------------------------- /lib/littlechat_web/gettext.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.Gettext do 2 | @moduledoc """ 3 | A module providing Internationalization with a gettext-based API. 4 | 5 | By using [Gettext](https://hexdocs.pm/gettext), 6 | your module gains a set of macros for translations, for example: 7 | 8 | import LittlechatWeb.Gettext 9 | 10 | # Simple translation 11 | gettext("Here is the string to translate") 12 | 13 | # Plural translation 14 | ngettext("Here is the string to translate", 15 | "Here are the strings to translate", 16 | 3) 17 | 18 | # Domain-based translation 19 | dgettext("errors", "Here is the error message to translate") 20 | 21 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. 22 | """ 23 | use Gettext, otp_app: :littlechat 24 | end 25 | -------------------------------------------------------------------------------- /lib/littlechat_web/router.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.Router do 2 | use LittlechatWeb, :router 3 | 4 | pipeline :browser do 5 | plug :accepts, ["html"] 6 | plug :fetch_session 7 | plug :fetch_live_flash 8 | plug :put_root_layout, {LittlechatWeb.LayoutView, :root} 9 | plug :protect_from_forgery 10 | plug :put_secure_browser_headers 11 | end 12 | 13 | pipeline :api do 14 | plug :accepts, ["json"] 15 | end 16 | 17 | scope "/", LittlechatWeb do 18 | pipe_through :browser 19 | 20 | get "/", PageController, :index 21 | 22 | scope "/room", as: :room do 23 | live "/new", Room.NewLive, :new 24 | live "/:slug", Room.ShowLive, :show 25 | end 26 | end 27 | 28 | # Other scopes may use custom stacks. 29 | # scope "/api", LittlechatWeb do 30 | # pipe_through :api 31 | # end 32 | end 33 | -------------------------------------------------------------------------------- /lib/littlechat/room.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.Room do 2 | @moduledoc """ 3 | Schema for creating video chat rooms. 4 | """ 5 | 6 | use Ecto.Schema 7 | import Ecto.Changeset 8 | 9 | schema "rooms" do 10 | field :title, :string 11 | field :slug, :string 12 | field :active_call, :boolean 13 | 14 | timestamps() 15 | end 16 | 17 | @fields [:title, :slug, :active_call] 18 | 19 | def changeset(room, attrs) do 20 | room 21 | |> cast(attrs, @fields) 22 | |> validate_required([:title, :slug]) 23 | |> format_slug() 24 | |> unique_constraint(:slug) 25 | end 26 | 27 | defp format_slug(%Ecto.Changeset{changes: %{slug: _}} = changeset) do 28 | changeset 29 | |> update_change(:slug, fn slug -> 30 | slug 31 | |> String.downcase() 32 | |> String.replace(" ", "-") 33 | end) 34 | end 35 | defp format_slug(changeset), do: changeset 36 | end 37 | -------------------------------------------------------------------------------- /assets/static/images/littlechat-favicon-transparent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /rel/vm.args: -------------------------------------------------------------------------------- 1 | ## This file provide the arguments provided to the VM at startup 2 | ## You can find a full list of flags and their behaviours at 3 | ## http://erlang.org/doc/man/erl.html 4 | 5 | ## Name of the node 6 | -name <%= release_name %>@127.0.0.1 7 | 8 | ## Cookie for distributed erlang 9 | -setcookie <%= release.profile.cookie %> 10 | 11 | ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive 12 | ## (Disabled by default..use with caution!) 13 | ##-heart 14 | 15 | ## Enable kernel poll and a few async threads 16 | ##+K true 17 | ##+A 5 18 | ## For OTP21+, the +A flag is not used anymore, 19 | ## +SDio replace it to use dirty schedulers 20 | ##+SDio 5 21 | 22 | ## Increase number of concurrent ports/sockets 23 | ##-env ERL_MAX_PORTS 4096 24 | 25 | ## Tweak GC to run more often 26 | ##-env ERL_FULLSWEEP_AFTER 10 27 | 28 | # Enable SMP automatically based on availability 29 | # On OTP21+, this is not needed anymore. 30 | -smp auto 31 | -------------------------------------------------------------------------------- /config/releases.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | database_url = 4 | System.get_env("DATABASE_URL") || 5 | raise """ 6 | environment variable DATABASE_URL is missing. 7 | For example: ecto://USER:PASS@HOST/DATABASE 8 | """ 9 | 10 | secret_key_base = 11 | System.get_env("SECRET_KEY_BASE") || 12 | raise """ 13 | environment variable SECRET_KEY_BASE is missing. 14 | You can generate one by calling: mix phx.gen.secret 15 | """ 16 | 17 | config :littlechat, LittlechatWeb.Endpoint, 18 | http: [ 19 | port: String.to_integer(System.get_env("PORT") || "4000"), 20 | transport_options: [socket_opts: [:inet6]] 21 | ], 22 | secret_key_base: secret_key_base 23 | 24 | # ## Using releases (Elixir v1.9+) 25 | # 26 | # If you are doing OTP releases, you need to instruct Phoenix 27 | # to start each relevant endpoint: 28 | # 29 | # 30 | # Then you can assemble a release by calling `mix release`. 31 | # See `mix help release` for more information. 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | littlechat-*.tar 24 | 25 | # If NPM crashes, it generates a log, let's ignore it too. 26 | npm-debug.log 27 | 28 | # The directory NPM downloads your dependencies sources to. 29 | /assets/node_modules/ 30 | 31 | # Since we are building assets from assets/, 32 | # we ignore priv/static. You may want to comment 33 | # this depending on your deployment strategy. 34 | /priv/static/ 35 | 36 | app.yaml 37 | -------------------------------------------------------------------------------- /assets/static/images/littlechat-favicon-centered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | -------------------------------------------------------------------------------- /assets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "repository": {}, 3 | "description": " ", 4 | "license": "MIT", 5 | "scripts": { 6 | "deploy": "webpack --mode production", 7 | "watch": "webpack --mode development --watch" 8 | }, 9 | "dependencies": { 10 | "nprogress": "^0.2.0", 11 | "phoenix": "file:../deps/phoenix", 12 | "phoenix_html": "file:../deps/phoenix_html", 13 | "phoenix_live_view": "file:../deps/phoenix_live_view", 14 | "regenerator-runtime": "^0.13.5", 15 | "webrtc-adapter": "^7.6.3" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.10.5", 19 | "@babel/preset-env": "^7.10.4", 20 | "@fortawesome/fontawesome-free": "^5.14.0", 21 | "babel-loader": "^8.0.0", 22 | "copy-webpack-plugin": "^6.0.3", 23 | "css-loader": "^3.6.0", 24 | "file-loader": "^6.0.0", 25 | "mini-css-extract-plugin": "^0.9.0", 26 | "node-sass": "^4.13.1", 27 | "optimize-css-assets-webpack-plugin": "^5.0.1", 28 | "sass": "^1.26.10", 29 | "sass-loader": "^8.0.2", 30 | "terser-webpack-plugin": "^2.3.2", 31 | "webpack": "4.41.5", 32 | "webpack-cli": "^3.3.12" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2020 Jesse G. Herrick and Littlelines, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | # 4 | # This configuration file is loaded before any dependency and 5 | # is restricted to this project. 6 | 7 | # General application configuration 8 | use Mix.Config 9 | 10 | config :littlechat, 11 | ecto_repos: [Littlechat.Repo] 12 | 13 | # Configures the endpoint 14 | config :littlechat, LittlechatWeb.Endpoint, 15 | url: [host: "localhost"], 16 | secret_key_base: "K6c8RVUnerfnlsZ+mW3rXg5uqrxv35Q0x36ARueLkTG7+R9EzcdG2iRdFzc7X/pX", 17 | render_errors: [view: LittlechatWeb.ErrorView, accepts: ~w(html json), layout: false], 18 | pubsub_server: Littlechat.PubSub, 19 | live_view: [signing_salt: "Esj+BTFi"] 20 | 21 | # Configures Elixir's Logger 22 | config :logger, :console, 23 | format: "$time $metadata[$level] $message\n", 24 | metadata: [:request_id] 25 | 26 | # Use Jason for JSON parsing in Phoenix 27 | config :phoenix, :json_library, Jason 28 | 29 | config :logger, 30 | backends: [:console, Sentry.LoggerBackend] 31 | 32 | # Import environment specific config. This must remain at the bottom 33 | # of this file so it overrides the configuration defined above. 34 | import_config "#{Mix.env()}.exs" 35 | -------------------------------------------------------------------------------- /lib/littlechat/application.ex: -------------------------------------------------------------------------------- 1 | defmodule Littlechat.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 | def start(_type, _args) do 9 | children = [ 10 | # Start the Ecto repository 11 | Littlechat.Repo, 12 | # Start the Telemetry supervisor 13 | LittlechatWeb.Telemetry, 14 | # Start the PubSub system 15 | {Phoenix.PubSub, name: Littlechat.PubSub}, 16 | # Start the Endpoint (http/https) 17 | LittlechatWeb.Presence, 18 | LittlechatWeb.Endpoint, 19 | LittlechatWeb.Stun 20 | # Start a worker by calling: Littlechat.Worker.start_link(arg) 21 | # {Littlechat.Worker, arg} 22 | ] 23 | 24 | # See https://hexdocs.pm/elixir/Supervisor.html 25 | # for other strategies and supported options 26 | opts = [strategy: :one_for_one, name: Littlechat.Supervisor] 27 | Supervisor.start_link(children, opts) 28 | end 29 | 30 | # Tell Phoenix to update the endpoint configuration 31 | # whenever the application is updated. 32 | def config_change(changed, _new, removed) do 33 | LittlechatWeb.Endpoint.config_change(changed, removed) 34 | :ok 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/littlechat_web/live/page_live.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.PageLive do 2 | use LittlechatWeb, :live_view 3 | 4 | @impl true 5 | def mount(_params, _session, socket) do 6 | {:ok, assign(socket, query: "", results: %{})} 7 | end 8 | 9 | @impl true 10 | def handle_event("suggest", %{"q" => query}, socket) do 11 | {:noreply, assign(socket, results: search(query), query: query)} 12 | end 13 | 14 | @impl true 15 | def handle_event("search", %{"q" => query}, socket) do 16 | case search(query) do 17 | %{^query => vsn} -> 18 | {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")} 19 | 20 | _ -> 21 | {:noreply, 22 | socket 23 | |> put_flash(:error, "No dependencies found matching \"#{query}\"") 24 | |> assign(results: %{}, query: query)} 25 | end 26 | end 27 | 28 | defp search(query) do 29 | if not LittlechatWeb.Endpoint.config(:code_reloader) do 30 | raise "action disabled when not in development" 31 | end 32 | 33 | for {app, desc, vsn} <- Application.started_applications(), 34 | app = to_string(app), 35 | String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"), 36 | into: %{}, 37 | do: {app, vsn} 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/support/channel_case.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.ChannelCase do 2 | @moduledoc """ 3 | This module defines the test case to be used by 4 | channel tests. 5 | 6 | Such tests rely on `Phoenix.ChannelTest` and also 7 | import other functionality to make it easier 8 | to build common data structures and query the data layer. 9 | 10 | Finally, if the test case interacts with the database, 11 | we enable the SQL sandbox, so changes done to the database 12 | are reverted at the end of every test. If you are using 13 | PostgreSQL, you can even run database tests asynchronously 14 | by setting `use LittlechatWeb.ChannelCase, async: true`, although 15 | this option is not recommended for other databases. 16 | """ 17 | 18 | use ExUnit.CaseTemplate 19 | 20 | using do 21 | quote do 22 | # Import conveniences for testing with channels 23 | import Phoenix.ChannelTest 24 | import LittlechatWeb.ChannelCase 25 | 26 | # The default endpoint for testing 27 | @endpoint LittlechatWeb.Endpoint 28 | end 29 | end 30 | 31 | setup tags do 32 | :ok = Ecto.Adapters.SQL.Sandbox.checkout(Littlechat.Repo) 33 | 34 | unless tags[:async] do 35 | Ecto.Adapters.SQL.Sandbox.mode(Littlechat.Repo, {:shared, self()}) 36 | end 37 | 38 | :ok 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/littlechat_web/channels/user_socket.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.UserSocket do 2 | use Phoenix.Socket 3 | 4 | ## Channels 5 | # channel "room:*", LittlechatWeb.RoomChannel 6 | channel "call:*", LittlechatWeb.CallChannel 7 | 8 | # Socket params are passed from the client and can 9 | # be used to verify and authenticate a user. After 10 | # verification, you can put default assigns into 11 | # the socket that will be set for all channels, ie 12 | # 13 | # {:ok, assign(socket, :user_id, verified_user_id)} 14 | # 15 | # To deny connection, return `:error`. 16 | # 17 | # See `Phoenix.Token` documentation for examples in 18 | # performing token verification on connect. 19 | @impl true 20 | def connect(_params, socket, _connect_info) do 21 | {:ok, socket} 22 | end 23 | 24 | # Socket id's are topics that allow you to identify all sockets for a given user: 25 | # 26 | # def id(socket), do: "user_socket:#{socket.assigns.user_id}" 27 | # 28 | # Would allow you to broadcast a "disconnect" event and terminate 29 | # all active sockets and channels for a given user: 30 | # 31 | # LittlechatWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) 32 | # 33 | # Returning `nil` makes this socket anonymous. 34 | @impl true 35 | def id(_socket), do: nil 36 | end 37 | -------------------------------------------------------------------------------- /assets/css/variables.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --black: #111111; 3 | --dark-gray: #232323; 4 | --gray: #666666; 5 | --light-gray: #F3F3F3; 6 | --white: #FFFFFF; 7 | --purple: #660099; 8 | --blue: #326DE6; 9 | --yellow: #EDB500; 10 | --magenta: #CC0066; 11 | } 12 | 13 | 14 | //////////////////// 15 | // Media Breakpoints 16 | //////////////////// 17 | $screen: "screen"; 18 | $breakpoint-small: 576px !default; 19 | $breakpoint-medium: 768px !default; 20 | $breakpoint-large: 992px !default; 21 | $breakpoint-xlarge: 1200px !default; 22 | $breakpoint-xxlarge: 1400px !default; 23 | 24 | //////////////////// 25 | // Media Queries 26 | //////////////////// 27 | $screen: "only screen"; 28 | 29 | $small-only: "#{$screen} and (max-width: #{$breakpoint-medium})"; 30 | 31 | $small-up: "#{$screen} and (max-width: #{$breakpoint-small})"; 32 | 33 | $medium-up: "#{$screen} and (min-width: #{$breakpoint-medium})"; 34 | 35 | $medium-only: "#{$screen} and (min-width: #{$breakpoint-medium}) and (max-width: #{$breakpoint-large})"; 36 | 37 | $large-up: "#{$screen} and (min-width: #{$breakpoint-large})"; 38 | 39 | $large-only: "#{$screen} and (min-width: #{$breakpoint-large}) and (max-width: #{$breakpoint-xlarge})"; 40 | 41 | $xlarge-up: "#{$screen} and (min-width: #{$breakpoint-xlarge})"; 42 | 43 | $xxlarge-up: "#{$screen} and (min-width: #{$breakpoint-xxlarge})"; 44 | -------------------------------------------------------------------------------- /assets/css/reset.scss: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video, input { 19 | box-sizing: border-box; 20 | margin: 0; 21 | padding: 0; 22 | border: 0; 23 | font-size: 100%; 24 | font: inherit; 25 | vertical-align: baseline; 26 | } 27 | /* HTML5 display-role reset for older browsers */ 28 | article, aside, details, figcaption, figure, 29 | footer, header, hgroup, menu, nav, section { 30 | display: block; 31 | } 32 | body { 33 | line-height: 1; 34 | font-family: 'Open Sans', sans-serif; 35 | font-style: italic; 36 | } 37 | ol, ul { 38 | list-style: none; 39 | } 40 | blockquote, q { 41 | quotes: none; 42 | } 43 | blockquote:before, blockquote:after, 44 | q:before, q:after { 45 | content: ''; 46 | content: none; 47 | } 48 | table { 49 | border-collapse: collapse; 50 | border-spacing: 0; 51 | } 52 | -------------------------------------------------------------------------------- /test/support/conn_case.ex: -------------------------------------------------------------------------------- 1 | defmodule LittlechatWeb.ConnCase do 2 | @moduledoc """ 3 | This module defines the test case to be used by 4 | tests that require setting up a connection. 5 | 6 | Such tests rely on `Phoenix.ConnTest` and also 7 | import other functionality to make it easier 8 | to build common data structures and query the data layer. 9 | 10 | Finally, if the test case interacts with the database, 11 | we enable the SQL sandbox, so changes done to the database 12 | are reverted at the end of every test. If you are using 13 | PostgreSQL, you can even run database tests asynchronously 14 | by setting `use LittlechatWeb.ConnCase, async: true`, although 15 | this option is not recommended for other databases. 16 | """ 17 | 18 | use ExUnit.CaseTemplate 19 | 20 | using do 21 | quote do 22 | # Import conveniences for testing with connections 23 | import Plug.Conn 24 | import Phoenix.ConnTest 25 | import LittlechatWeb.ConnCase 26 | 27 | alias LittlechatWeb.Router.Helpers, as: Routes 28 | 29 | # The default endpoint for testing 30 | @endpoint LittlechatWeb.Endpoint 31 | end 32 | end 33 | 34 | setup tags do 35 | :ok = Ecto.Adapters.SQL.Sandbox.checkout(Littlechat.Repo) 36 | 37 | unless tags[:async] do 38 | Ecto.Adapters.SQL.Sandbox.mode(Littlechat.Repo, {:shared, self()}) 39 | end 40 | 41 | {:ok, conn: Phoenix.ConnTest.build_conn()} 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /assets/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const glob = require('glob'); 3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 4 | const TerserPlugin = require('terser-webpack-plugin'); 5 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); 6 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 7 | 8 | module.exports = (env, options) => { 9 | const devMode = options.mode !== 'production'; 10 | 11 | return { 12 | optimization: { 13 | minimizer: [ 14 | new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }), 15 | new OptimizeCSSAssetsPlugin({}) 16 | ] 17 | }, 18 | entry: { 19 | 'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']) 20 | }, 21 | output: { 22 | filename: '[name].js', 23 | path: path.resolve(__dirname, '../priv/static/js'), 24 | publicPath: '/js/' 25 | }, 26 | devtool: devMode ? 'source-map' : undefined, 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.js$/, 31 | exclude: /node_modules/, 32 | use: { 33 | loader: 'babel-loader' 34 | } 35 | }, 36 | { 37 | test: /\.[s]?css$/, 38 | use: [ 39 | MiniCssExtractPlugin.loader, 40 | 'css-loader', 41 | 'sass-loader', 42 | ], 43 | }, 44 | { 45 | test: /\.(svg|eot|woff|woff2|ttf)$/, 46 | use: ['file-loader'] 47 | } 48 | ] 49 | }, 50 | plugins: [ 51 | new MiniCssExtractPlugin({ filename: '../css/app.css' }), 52 | new CopyWebpackPlugin({ patterns: [{ from: "static/", to: "../" }] }) 53 | ] 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /lib/littlechat_web/live/page_live.html.leex: -------------------------------------------------------------------------------- 1 |Peace-of-mind from prototype to production
4 | 5 | 14 |