Browse Source

feat(project): Adding basis.

jackyalcine 7 months ago
parent
commit
d567668fcf
Signed by: Jacky Alciné <yo@jacky.wtf> GPG Key ID: 537A4F904B15268D
48 changed files with 1301 additions and 0 deletions
  1. 11
    0
      .dockerignore
  2. 5
    0
      .formatter.exs
  3. 36
    0
      .gitignore
  4. 27
    0
      Dockerfile
  5. 25
    0
      Dockerfile.dev
  6. 19
    0
      README.md
  7. 32
    0
      config/config.exs
  8. 67
    0
      config/dev.exs
  9. 71
    0
      config/prod.exs
  10. 18
    0
      config/test.exs
  11. 39
    0
      docker-compose.yml
  12. 11
    0
      docker/rootfs/root/.npmrc
  13. 29
    0
      docker/scripts/build.sh
  14. 8
    0
      docker/scripts/cleanup.sh
  15. 4
    0
      docker/scripts/entrypoint.sh
  16. 5
    0
      docker/scripts/healthcheck.sh
  17. 7
    0
      docker/scripts/post-deploy.sh
  18. 19
    0
      docker/scripts/pre-deploy.sh
  19. 36
    0
      docker/scripts/prepare.sh
  20. 9
    0
      lib/koype_publish.ex
  21. 31
    0
      lib/koype_publish/application.ex
  22. 5
    0
      lib/koype_publish/repo.ex
  23. 69
    0
      lib/koype_publish_web.ex
  24. 33
    0
      lib/koype_publish_web/channels/user_socket.ex
  25. 7
    0
      lib/koype_publish_web/controllers/page_controller.ex
  26. 46
    0
      lib/koype_publish_web/endpoint.ex
  27. 24
    0
      lib/koype_publish_web/gettext.ex
  28. 26
    0
      lib/koype_publish_web/router.ex
  29. 30
    0
      lib/koype_publish_web/templates/layout/app.html.eex
  30. 35
    0
      lib/koype_publish_web/templates/page/index.html.eex
  31. 44
    0
      lib/koype_publish_web/views/error_helpers.ex
  32. 16
    0
      lib/koype_publish_web/views/error_view.ex
  33. 3
    0
      lib/koype_publish_web/views/layout_view.ex
  34. 3
    0
      lib/koype_publish_web/views/page_view.ex
  35. 62
    0
      mix.exs
  36. 24
    0
      mix.lock
  37. 97
    0
      priv/gettext/en/LC_MESSAGES/errors.po
  38. 95
    0
      priv/gettext/errors.pot
  39. 4
    0
      priv/repo/migrations/.formatter.exs
  40. 11
    0
      priv/repo/seeds.exs
  41. 8
    0
      test/koype_publish_web/controllers/page_controller_test.exs
  42. 14
    0
      test/koype_publish_web/views/error_view_test.exs
  43. 3
    0
      test/koype_publish_web/views/layout_view_test.exs
  44. 3
    0
      test/koype_publish_web/views/page_view_test.exs
  45. 37
    0
      test/support/channel_case.ex
  46. 38
    0
      test/support/conn_case.ex
  47. 53
    0
      test/support/data_case.ex
  48. 2
    0
      test/test_helper.exs

+ 11
- 0
.dockerignore View File

@@ -0,0 +1,11 @@
1
+deps/
2
+_build/
3
+docker-compose.yml
4
+.git/*
5
+.elixir_ls/*
6
+.envrc
7
+.elixir-version
8
+.editiorconfig
9
+erl_crash.dump
10
+node_modules/
11
+tmp/

+ 5
- 0
.formatter.exs View File

@@ -0,0 +1,5 @@
1
+[
2
+  import_deps: [:ecto, :phoenix],
3
+  inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"],
4
+  subdirectories: ["priv/*/migrations"]
5
+]

+ 36
- 0
.gitignore View File

@@ -0,0 +1,36 @@
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
+koype_publish-*.tar
24
+
25
+# Since we are building assets from assets/,
26
+# we ignore priv/static. You may want to comment
27
+# this depending on your deployment strategy.
28
+/priv/static/
29
+
30
+# Files matching config/*.secret.exs pattern contain sensitive
31
+# data and you should not commit them into version control.
32
+#
33
+# Alternatively, you may comment the line below and commit the
34
+# secrets files as long as you replace their contents by environment
35
+# variables.
36
+/config/*.secret.exs

+ 27
- 0
Dockerfile View File

@@ -0,0 +1,27 @@
1
+FROM elixir:1.7.4-alpine
2
+LABEL maintainer Jacky Alcine <yo@jacky.wtf>
3
+
4
+ARG MIX_ENV
5
+
6
+ENV MIX_ENV=${MIX_ENV:-prod} \
7
+  TZ=Etc/UTC \
8
+  REPLACE_OS_VARS=true
9
+
10
+ADD docker/rootfs/ /
11
+
12
+RUN mkdir /tmp/koype-publish-docker
13
+COPY docker/rootfs /
14
+ADD docker/scripts/ /tmp/koype-publish-docker/
15
+
16
+RUN sh /tmp/koype-publish-docker/prepare.sh
17
+
18
+WORKDIR /opt/koype/publish
19
+
20
+COPY . /opt/koype/publish/
21
+VOLUME /opt/koype/publish/priv/repo/db/
22
+RUN sh /tmp/koype-publish-docker/build.sh
23
+
24
+RUN sh /tmp/koype-publish-docker/cleanup.sh
25
+
26
+SHELL ["/bin/bash"]
27
+CMD ["/tmp/koype-publish-docker/entrypoint.sh"]

+ 25
- 0
Dockerfile.dev View File

@@ -0,0 +1,25 @@
1
+FROM elixir:1.7.4-alpine
2
+LABEL maintainer Jacky Alcine <yo@jacky.wtf>
3
+
4
+ARG MIX_ENV
5
+
6
+ENV MIX_ENV=${MIX_ENV:-prod} \
7
+  TZ=Etc/UTC \
8
+  REPLACE_OS_VARS=true
9
+
10
+ADD docker/rootfs/ /
11
+
12
+RUN mkdir /tmp/koype-publish-docker
13
+COPY docker/rootfs /
14
+ADD docker/scripts/ /tmp/koype-publish-docker/
15
+
16
+RUN sh /tmp/koype-publish-docker/prepare.sh
17
+
18
+WORKDIR /opt/koype/publish
19
+
20
+ADD . /opt/koype/publish
21
+
22
+RUN sh /tmp/koype-publish-docker/build.sh
23
+
24
+SHELL ["/bin/bash"]
25
+CMD ["/tmp/koype-publish-docker/entrypoint.sh"]

+ 19
- 0
README.md View File

@@ -0,0 +1,19 @@
1
+# Koype.Publish
2
+
3
+To start your Phoenix server:
4
+
5
+  * Install dependencies with `mix deps.get`
6
+  * Create and migrate your database with `mix ecto.setup`
7
+  * Start Phoenix endpoint with `mix phx.server`
8
+
9
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
10
+
11
+Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
12
+
13
+## Learn more
14
+
15
+  * Official website: http://www.phoenixframework.org/
16
+  * Guides: https://hexdocs.pm/phoenix/overview.html
17
+  * Docs: https://hexdocs.pm/phoenix
18
+  * Mailing list: http://groups.google.com/group/phoenix-talk
19
+  * Source: https://github.com/phoenixframework/phoenix

+ 32
- 0
config/config.exs View File

@@ -0,0 +1,32 @@
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 :koype_publish,
11
+  namespace: Koype.Publish,
12
+  ecto_repos: [Koype.Publish.Repo],
13
+  generators: [binary_id: true]
14
+
15
+# Configures the endpoint
16
+config :koype_publish, Koype.PublishWeb.Endpoint,
17
+  url: [host: "localhost"],
18
+  secret_key_base: "sa9LA8od8eoD+I45nyuTJr6Nf+DRilitEzdZa1BM+oODt0kqeNcB+8t9s9eE/1zU",
19
+  render_errors: [view: Koype.PublishWeb.ErrorView, accepts: ~w(html json)],
20
+  pubsub: [name: Koype.Publish.PubSub, adapter: Phoenix.PubSub.PG2]
21
+
22
+# Configures Elixir's Logger
23
+config :logger, :console,
24
+  format: "$time $metadata[$level] $message\n",
25
+  metadata: [:request_id]
26
+
27
+# Use Jason for JSON parsing in Phoenix
28
+config :phoenix, :json_library, Jason
29
+
30
+# Import environment specific config. This must remain at the bottom
31
+# of this file so it overrides the configuration defined above.
32
+import_config "#{Mix.env()}.exs"

+ 67
- 0
config/dev.exs View File

@@ -0,0 +1,67 @@
1
+use Mix.Config
2
+
3
+# For development, we disable any cache and enable
4
+# debugging and code reloading.
5
+#
6
+# The watchers configuration can be used to run external
7
+# watchers to your application. For example, we use it
8
+# with webpack to recompile .js and .css sources.
9
+config :koype_publish, Koype.PublishWeb.Endpoint,
10
+  http: [port: 4000],
11
+  debug_errors: true,
12
+  code_reloader: true,
13
+  check_origin: false,
14
+  watchers: []
15
+
16
+# ## SSL Support
17
+#
18
+# In order to use HTTPS in development, a self-signed
19
+# certificate can be generated by running the following
20
+# Mix task:
21
+#
22
+#     mix phx.gen.cert
23
+#
24
+# Note that this task requires Erlang/OTP 20 or later.
25
+# Run `mix help phx.gen.cert` for more information.
26
+#
27
+# The `http:` config above can be replaced with:
28
+#
29
+#     https: [
30
+#       port: 4001,
31
+#       cipher_suite: :strong,
32
+#       keyfile: "priv/cert/selfsigned_key.pem",
33
+#       certfile: "priv/cert/selfsigned.pem"
34
+#     ],
35
+#
36
+# If desired, both `http:` and `https:` keys can be
37
+# configured to run both http and https servers on
38
+# different ports.
39
+
40
+# Watch static and templates for browser reloading.
41
+config :koype_publish, Koype.PublishWeb.Endpoint,
42
+  live_reload: [
43
+    patterns: [
44
+      ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
45
+      ~r{priv/gettext/.*(po)$},
46
+      ~r{lib/koype_publish_web/views/.*(ex)$},
47
+      ~r{lib/koype_publish_web/templates/.*(eex)$}
48
+    ]
49
+  ]
50
+
51
+# Do not include metadata nor timestamps in development logs
52
+config :logger, :console, format: "[$level] $message\n"
53
+
54
+# Set a higher stacktrace during development. Avoid configuring such
55
+# in production as building large stacktraces may be expensive.
56
+config :phoenix, :stacktrace_depth, 20
57
+
58
+# Initialize plugs at runtime for faster development compilation
59
+config :phoenix, :plug_init_mode, :runtime
60
+
61
+# Configure your database
62
+config :koype_publish, Koype.Publish.Repo,
63
+  username: "postgres",
64
+  password: "postgres",
65
+  database: "koype_publish_dev",
66
+  hostname: "localhost",
67
+  pool_size: 10

+ 71
- 0
config/prod.exs View File

@@ -0,0 +1,71 @@
1
+use Mix.Config
2
+
3
+# For production, don't forget to configure the url host
4
+# to something meaningful, Phoenix uses this information
5
+# when generating URLs.
6
+#
7
+# Note we also include the path to a cache manifest
8
+# containing the digested version of static files. This
9
+# manifest is generated by the `mix phx.digest` task,
10
+# which you should run after static files are built and
11
+# before starting your production server.
12
+config :koype_publish, Koype.PublishWeb.Endpoint,
13
+  http: [:inet6, port: System.get_env("PORT") || 4000],
14
+  url: [host: "example.com", port: 80],
15
+  cache_static_manifest: "priv/static/cache_manifest.json"
16
+
17
+# Do not print debug messages in production
18
+config :logger, level: :info
19
+
20
+# ## SSL Support
21
+#
22
+# To get SSL working, you will need to add the `https` key
23
+# to the previous section and set your `:url` port to 443:
24
+#
25
+#     config :koype_publish, Koype.PublishWeb.Endpoint,
26
+#       ...
27
+#       url: [host: "example.com", port: 443],
28
+#       https: [
29
+#         :inet6,
30
+#         port: 443,
31
+#         cipher_suite: :strong,
32
+#         keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
33
+#         certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
34
+#       ]
35
+#
36
+# The `cipher_suite` is set to `:strong` to support only the
37
+# latest and more secure SSL ciphers. This means old browsers
38
+# and clients may not be supported. You can set it to
39
+# `:compatible` for wider support.
40
+#
41
+# `:keyfile` and `:certfile` expect an absolute path to the key
42
+# and cert in disk or a relative path inside priv, for example
43
+# "priv/ssl/server.key". For all supported SSL configuration
44
+# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
45
+#
46
+# We also recommend setting `force_ssl` in your endpoint, ensuring
47
+# no data is ever sent via http, always redirecting to https:
48
+#
49
+#     config :koype_publish, Koype.PublishWeb.Endpoint,
50
+#       force_ssl: [hsts: true]
51
+#
52
+# Check `Plug.SSL` for all available options in `force_ssl`.
53
+
54
+# ## Using releases (distillery)
55
+#
56
+# If you are doing OTP releases, you need to instruct Phoenix
57
+# to start the server for all endpoints:
58
+#
59
+#     config :phoenix, :serve_endpoints, true
60
+#
61
+# Alternatively, you can configure exactly which server to
62
+# start per endpoint:
63
+#
64
+#     config :koype_publish, Koype.PublishWeb.Endpoint, server: true
65
+#
66
+# Note you can't rely on `System.get_env/1` when using releases.
67
+# See the releases documentation accordingly.
68
+
69
+# Finally import the config/prod.secret.exs which should be versioned
70
+# separately.
71
+import_config "prod.secret.exs"

+ 18
- 0
config/test.exs View File

@@ -0,0 +1,18 @@
1
+use Mix.Config
2
+
3
+# We don't run a server during test. If one is required,
4
+# you can enable the server option below.
5
+config :koype_publish, Koype.PublishWeb.Endpoint,
6
+  http: [port: 4002],
7
+  server: false
8
+
9
+# Print only warnings and errors during test
10
+config :logger, level: :warn
11
+
12
+# Configure your database
13
+config :koype_publish, Koype.Publish.Repo,
14
+  username: "postgres",
15
+  password: "postgres",
16
+  database: "koype_publish_test",
17
+  hostname: "localhost",
18
+  pool: Ecto.Adapters.SQL.Sandbox

+ 39
- 0
docker-compose.yml View File

@@ -0,0 +1,39 @@
1
+---
2
+version: "3.4"
3
+services:
4
+  site:
5
+    build:
6
+      context: "."
7
+      dockerfile: Dockerfile.dev
8
+      args:
9
+        MIX_ENV: dev
10
+    environment:
11
+      GUARDIAN_SECRET_KEY: ${GUARDIAN_SECRET_KEY}
12
+      MIX_ENV: dev
13
+      ENV: dev
14
+      PORT: ${PORT}
15
+      TEST_PORT: ${TEST_PORT}
16
+      TEST_HOST: ${TEST_HOST}
17
+      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
18
+      SESSION_SIGNING_SALT: ${SESSION_SIGNING_SALT}
19
+    ports:
20
+      - "${PORT}:${PORT}"
21
+    volumes:
22
+      - ./:/opt/koype/publish/:z
23
+      - ./priv/repo/db/:/opt/koype/publish/priv/repo/db/:z
24
+      - mix_deps:/opt/koype/publish/deps/:rw
25
+      - mix_build:/opt/koype/publish/_build/:rw
26
+    healthcheck:
27
+      test: ["CMD", "/tmp/koype-publish-docker/healthcheck.sh"]
28
+      interval: 60s
29
+      timeout: 5s
30
+      retries: 5
31
+    networks:
32
+      - network
33
+
34
+networks:
35
+  network:
36
+
37
+volumes:
38
+  mix_deps:
39
+  mix_build:

+ 11
- 0
docker/rootfs/root/.npmrc View File

@@ -0,0 +1,11 @@
1
+color=false
2
+exact=true
3
+link=false
4
+long=true
5
+optional=false
6
+progress=true
7
+save-exact=true
8
+usage=false
9
+verbose=true
10
+version=true
11
+viewer=less

+ 29
- 0
docker/scripts/build.sh View File

@@ -0,0 +1,29 @@
1
+#!/bin/sh
2
+
3
+HEX_HTTP_CONCURRENCY=5
4
+HEX_HTTP_TIMEOUT=600
5
+NODE_ENV=${ENV}
6
+NPM_CONFIG_LINK=false
7
+NPM_CONFIG_PROGRESS=false
8
+
9
+apk add git
10
+
11
+echo " ---> [npm] Pulling dependencies..."
12
+npm install -g npm@latest npx@latest
13
+npm install || exit 50
14
+
15
+echo " ---> [mix] Preparing..."
16
+mix local.hex --force || exit 10
17
+mix local.rebar --force || exit 10
18
+
19
+echo " ---> [mix] Fetching dependencies..."
20
+mix deps.clean --all || exit 20
21
+mix deps.get || exit 21
22
+
23
+echo " ---> [mix] Building dependencies..."
24
+mix deps.compile || exit 30
25
+
26
+echo " ---> [mix] Compiling application..."
27
+mix compile || exit 40
28
+
29
+echo " ---> [koype] Application built."

+ 8
- 0
docker/scripts/cleanup.sh View File

@@ -0,0 +1,8 @@
1
+#!/bin/sh
2
+
3
+if [ "${MIX_ENV}" = "prod" ]; then
4
+  echo "[cleanup] ---> Removing build dependencies..."
5
+  apk del build
6
+else
7
+  echo "[cleanup] ---> Skipping because not in production."
8
+fi

+ 4
- 0
docker/scripts/entrypoint.sh View File

@@ -0,0 +1,4 @@
1
+#!/bin/sh
2
+
3
+cd /opt/koype/publish || exit 10
4
+mix phx.server

+ 5
- 0
docker/scripts/healthcheck.sh View File

@@ -0,0 +1,5 @@
1
+#!/bin/sh
2
+
3
+# TODO: Hit an endpoint and expect "OK", 200 to come back.
4
+
5
+curl -f "http://${HOST}:${PORT}/version"

+ 7
- 0
docker/scripts/post-deploy.sh View File

@@ -0,0 +1,7 @@
1
+#!/bin/sh
2
+
3
+echo " ----> [deploy:post] Creating database file..."
4
+touch "/opt/koype/publish/priv/repo/db/${MIX_ENV:-prod}.db" || exit 15
5
+
6
+echo " ----> [deploy:post] Setting up database..."
7
+mix ecto.setup || exit 20

+ 19
- 0
docker/scripts/pre-deploy.sh View File

@@ -0,0 +1,19 @@
1
+#!/bin/sh
2
+
3
+cd /opt/koype/publish || exit 10
4
+
5
+echo " ----> [deploy:pre] Installing needed CLI tools..."
6
+npm install || exit 20
7
+npm install --global parcel-bundler || exit 30
8
+
9
+echo " ----> [deploy:pre] Building static resources..."
10
+npm run parcel:build || exit 40
11
+
12
+echo " ----> [deploy:pre] <skip> Confirm permissions on object storage..."
13
+# mix koype.storage_check || exit 50
14
+
15
+echo " ----> [deploy:pre] <skip> Run production-ready checks... "
16
+# mix koype.smoke_test || exit 60
17
+
18
+echo " ----> [deploy:pre] Update static digests..."
19
+mix phx.digest || exit 50

+ 36
- 0
docker/scripts/prepare.sh View File

@@ -0,0 +1,36 @@
1
+#!/bin/sh
2
+
3
+ONE_WEEK_IN_MINUTES=10080 
4
+
5
+echo " ---> [apk] Syncing repos (allowed to fail)..."
6
+apk update --cache-max-age="${ONE_WEEK_IN_MINUTES}"
7
+
8
+
9
+echo " ---> [apk] Fetching baseline packages..."
10
+apk add \
11
+  bash \
12
+  ca-certificates \
13
+  coreutils \
14
+  tzdata \
15
+  curl \
16
+  inotify-tools \
17
+  imagemagick \
18
+  nodejs \
19
+  npm \
20
+  sqlite-libs \
21
+  || exit 20
22
+
23
+echo " ---> [apk] Fetching development packages..."
24
+apk add --virtual=build \
25
+  gcc \
26
+  util-linux \
27
+  build-base \
28
+  binutils-dev \
29
+  libelf-dev \
30
+  sqlite-dev \
31
+  || exit 30
32
+
33
+echo " ---> [apk] Syncing cache... "
34
+apk cache sync
35
+
36
+mkdir -p /opt/koype/publish

+ 9
- 0
lib/koype_publish.ex View File

@@ -0,0 +1,9 @@
1
+defmodule Koype.Publish do
2
+  @moduledoc """
3
+  Koype.Publish 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

+ 31
- 0
lib/koype_publish/application.ex View File

@@ -0,0 +1,31 @@
1
+defmodule Koype.Publish.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
+    # List all child processes to be supervised
10
+    children = [
11
+      # Start the Ecto repository
12
+      Koype.Publish.Repo,
13
+      # Start the endpoint when the application starts
14
+      Koype.PublishWeb.Endpoint
15
+      # Starts a worker by calling: Koype.Publish.Worker.start_link(arg)
16
+      # {Koype.Publish.Worker, arg},
17
+    ]
18
+
19
+    # See https://hexdocs.pm/elixir/Supervisor.html
20
+    # for other strategies and supported options
21
+    opts = [strategy: :one_for_one, name: Koype.Publish.Supervisor]
22
+    Supervisor.start_link(children, opts)
23
+  end
24
+
25
+  # Tell Phoenix to update the endpoint configuration
26
+  # whenever the application is updated.
27
+  def config_change(changed, _new, removed) do
28
+    Koype.PublishWeb.Endpoint.config_change(changed, removed)
29
+    :ok
30
+  end
31
+end

+ 5
- 0
lib/koype_publish/repo.ex View File

@@ -0,0 +1,5 @@
1
+defmodule Koype.Publish.Repo do
2
+  use Ecto.Repo,
3
+    otp_app: :koype_publish,
4
+    adapter: Ecto.Adapters.Postgres
5
+end

+ 69
- 0
lib/koype_publish_web.ex View File

@@ -0,0 +1,69 @@
1
+defmodule Koype.PublishWeb do
2
+  @moduledoc """
3
+  The entrypoint for defining your web interface, such
4
+  as controllers, views, channels and so on.
5
+
6
+  This can be used in your application as:
7
+
8
+      use Koype.PublishWeb, :controller
9
+      use Koype.PublishWeb, :view
10
+
11
+  The definitions below will be executed for every view,
12
+  controller, etc, so keep them short and clean, focused
13
+  on imports, uses and aliases.
14
+
15
+  Do NOT define functions inside the quoted expressions
16
+  below. Instead, define any helper function in modules
17
+  and import those modules here.
18
+  """
19
+
20
+  def controller do
21
+    quote do
22
+      use Phoenix.Controller, namespace: Koype.PublishWeb
23
+
24
+      import Plug.Conn
25
+      import Koype.PublishWeb.Gettext
26
+      alias Koype.PublishWeb.Router.Helpers, as: Routes
27
+    end
28
+  end
29
+
30
+  def view do
31
+    quote do
32
+      use Phoenix.View,
33
+        root: "lib/koype_publish_web/templates",
34
+        namespace: Koype.PublishWeb
35
+
36
+      # Import convenience functions from controllers
37
+      import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
38
+
39
+      # Use all HTML functionality (forms, tags, etc)
40
+      use Phoenix.HTML
41
+
42
+      import Koype.PublishWeb.ErrorHelpers
43
+      import Koype.PublishWeb.Gettext
44
+      alias Koype.PublishWeb.Router.Helpers, as: Routes
45
+    end
46
+  end
47
+
48
+  def router do
49
+    quote do
50
+      use Phoenix.Router
51
+      import Plug.Conn
52
+      import Phoenix.Controller
53
+    end
54
+  end
55
+
56
+  def channel do
57
+    quote do
58
+      use Phoenix.Channel
59
+      import Koype.PublishWeb.Gettext
60
+    end
61
+  end
62
+
63
+  @doc """
64
+  When used, dispatch to the appropriate controller/view/etc.
65
+  """
66
+  defmacro __using__(which) when is_atom(which) do
67
+    apply(__MODULE__, which, [])
68
+  end
69
+end

+ 33
- 0
lib/koype_publish_web/channels/user_socket.ex View File

@@ -0,0 +1,33 @@
1
+defmodule Koype.PublishWeb.UserSocket do
2
+  use Phoenix.Socket
3
+
4
+  ## Channels
5
+  # channel "room:*", Koype.PublishWeb.RoomChannel
6
+
7
+  # Socket params are passed from the client and can
8
+  # be used to verify and authenticate a user. After
9
+  # verification, you can put default assigns into
10
+  # the socket that will be set for all channels, ie
11
+  #
12
+  #     {:ok, assign(socket, :user_id, verified_user_id)}
13
+  #
14
+  # To deny connection, return `:error`.
15
+  #
16
+  # See `Phoenix.Token` documentation for examples in
17
+  # performing token verification on connect.
18
+  def connect(_params, socket, _connect_info) do
19
+    {:ok, socket}
20
+  end
21
+
22
+  # Socket id's are topics that allow you to identify all sockets for a given user:
23
+  #
24
+  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
25
+  #
26
+  # Would allow you to broadcast a "disconnect" event and terminate
27
+  # all active sockets and channels for a given user:
28
+  #
29
+  #     Koype.PublishWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
30
+  #
31
+  # Returning `nil` makes this socket anonymous.
32
+  def id(_socket), do: nil
33
+end

+ 7
- 0
lib/koype_publish_web/controllers/page_controller.ex View File

@@ -0,0 +1,7 @@
1
+defmodule Koype.PublishWeb.PageController do
2
+  use Koype.PublishWeb, :controller
3
+
4
+  def index(conn, _params) do
5
+    render(conn, "index.html")
6
+  end
7
+end

+ 46
- 0
lib/koype_publish_web/endpoint.ex View File

@@ -0,0 +1,46 @@
1
+defmodule Koype.PublishWeb.Endpoint do
2
+  use Phoenix.Endpoint, otp_app: :koype_publish
3
+
4
+  socket "/socket", Koype.PublishWeb.UserSocket,
5
+    websocket: true,
6
+    longpoll: false
7
+
8
+  # Serve at "/" the static files from "priv/static" directory.
9
+  #
10
+  # You should set gzip to true if you are running phx.digest
11
+  # when deploying your static files in production.
12
+  plug Plug.Static,
13
+    at: "/",
14
+    from: :koype_publish,
15
+    gzip: false,
16
+    only: ~w(css fonts images js favicon.ico robots.txt)
17
+
18
+  # Code reloading can be explicitly enabled under the
19
+  # :code_reloader configuration of your endpoint.
20
+  if code_reloading? do
21
+    socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
22
+    plug Phoenix.LiveReloader
23
+    plug Phoenix.CodeReloader
24
+  end
25
+
26
+  plug Plug.RequestId
27
+  plug Plug.Logger
28
+
29
+  plug Plug.Parsers,
30
+    parsers: [:urlencoded, :multipart, :json],
31
+    pass: ["*/*"],
32
+    json_decoder: Phoenix.json_library()
33
+
34
+  plug Plug.MethodOverride
35
+  plug Plug.Head
36
+
37
+  # The session will be stored in the cookie and signed,
38
+  # this means its contents can be read but not tampered with.
39
+  # Set :encryption_salt if you would also like to encrypt it.
40
+  plug Plug.Session,
41
+    store: :cookie,
42
+    key: "_koype_publish_key",
43
+    signing_salt: "x2HTOamp"
44
+
45
+  plug Koype.PublishWeb.Router
46
+end

+ 24
- 0
lib/koype_publish_web/gettext.ex View File

@@ -0,0 +1,24 @@
1
+defmodule Koype.PublishWeb.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 Koype.PublishWeb.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: :koype_publish
24
+end

+ 26
- 0
lib/koype_publish_web/router.ex View File

@@ -0,0 +1,26 @@
1
+defmodule Koype.PublishWeb.Router do
2
+  use Koype.PublishWeb, :router
3
+
4
+  pipeline :browser do
5
+    plug :accepts, ["html"]
6
+    plug :fetch_session
7
+    plug :fetch_flash
8
+    plug :protect_from_forgery
9
+    plug :put_secure_browser_headers
10
+  end
11
+
12
+  pipeline :api do
13
+    plug :accepts, ["json"]
14
+  end
15
+
16
+  scope "/", Koype.PublishWeb do
17
+    pipe_through :browser
18
+
19
+    get "/", PageController, :index
20
+  end
21
+
22
+  # Other scopes may use custom stacks.
23
+  # scope "/api", Koype.PublishWeb do
24
+  #   pipe_through :api
25
+  # end
26
+end

+ 30
- 0
lib/koype_publish_web/templates/layout/app.html.eex View File

@@ -0,0 +1,30 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+  <head>
4
+    <meta charset="utf-8"/>
5
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
6
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
+    <title>Koype.Publish · Phoenix Framework</title>
8
+    <link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
9
+  </head>
10
+  <body>
11
+    <header>
12
+      <section class="container">
13
+        <nav role="navigation">
14
+          <ul>
15
+            <li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
16
+          </ul>
17
+        </nav>
18
+        <a href="http://phoenixframework.org/" class="phx-logo">
19
+          <img src="<%= Routes.static_path(@conn, "/images/phoenix.png") %>" alt="Phoenix Framework Logo"/>
20
+        </a>
21
+      </section>
22
+    </header>
23
+    <main role="main" class="container">
24
+      <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
25
+      <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
26
+      <%= render @view_module, @view_template, assigns %>
27
+    </main>
28
+    <script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
29
+  </body>
30
+</html>

+ 35
- 0
lib/koype_publish_web/templates/page/index.html.eex View File

@@ -0,0 +1,35 @@
1
+<section class="phx-hero">
2
+  <h1><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1>
3
+  <p>A productive web framework that<br/>does not compromise speed and maintainability.</p>
4
+</section>
5
+
6
+<section class="row">
7
+  <article class="column">
8
+    <h2>Resources</h2>
9
+    <ul>
10
+      <li>
11
+        <a href="https://hexdocs.pm/phoenix/overview.html">Guides &amp; Docs</a>
12
+      </li>
13
+      <li>
14
+        <a href="https://github.com/phoenixframework/phoenix">Source</a>
15
+      </li>
16
+      <li>
17
+        <a href="https://github.com/phoenixframework/phoenix/blob/v1.4/CHANGELOG.md">v1.4 Changelog</a>
18
+      </li>
19
+    </ul>
20
+  </article>
21
+  <article class="column">
22
+    <h2>Help</h2>
23
+    <ul>
24
+      <li>
25
+        <a href="https://elixirforum.com/c/phoenix-forum">Forum</a>
26
+      </li>
27
+      <li>
28
+        <a href="https://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on Freenode IRC</a>
29
+      </li>
30
+      <li>
31
+        <a href="https://twitter.com/elixirphoenix">Twitter @elixirphoenix</a>
32
+      </li>
33
+    </ul>
34
+  </article>
35
+</section>

+ 44
- 0
lib/koype_publish_web/views/error_helpers.ex View File

@@ -0,0 +1,44 @@
1
+defmodule Koype.PublishWeb.ErrorHelpers do
2
+  @moduledoc """
3
+  Conveniences for translating and building error messages.
4
+  """
5
+
6
+  use Phoenix.HTML
7
+
8
+  @doc """
9
+  Generates tag for inlined form input errors.
10
+  """
11
+  def error_tag(form, field) do
12
+    Enum.map(Keyword.get_values(form.errors, field), fn error ->
13
+      content_tag(:span, translate_error(error), class: "help-block")
14
+    end)
15
+  end
16
+
17
+  @doc """
18
+  Translates an error message using gettext.
19
+  """
20
+  def translate_error({msg, opts}) do
21
+    # When using gettext, we typically pass the strings we want
22
+    # to translate as a static argument:
23
+    #
24
+    #     # Translate "is invalid" in the "errors" domain
25
+    #     dgettext("errors", "is invalid")
26
+    #
27
+    #     # Translate the number of files with plural rules
28
+    #     dngettext("errors", "1 file", "%{count} files", count)
29
+    #
30
+    # Because the error messages we show in our forms and APIs
31
+    # are defined inside Ecto, we need to translate them dynamically.
32
+    # This requires us to call the Gettext module passing our gettext
33
+    # backend as first argument.
34
+    #
35
+    # Note we use the "errors" domain, which means translations
36
+    # should be written to the errors.po file. The :count option is
37
+    # set by Ecto and indicates we should also apply plural rules.
38
+    if count = opts[:count] do
39
+      Gettext.dngettext(Koype.PublishWeb.Gettext, "errors", msg, msg, count, opts)
40
+    else
41
+      Gettext.dgettext(Koype.PublishWeb.Gettext, "errors", msg, opts)
42
+    end
43
+  end
44
+end

+ 16
- 0
lib/koype_publish_web/views/error_view.ex View File

@@ -0,0 +1,16 @@
1
+defmodule Koype.PublishWeb.ErrorView do
2
+  use Koype.PublishWeb, :view
3
+
4
+  # If you want to customize a particular status code
5
+  # for a certain format, you may uncomment below.
6
+  # def render("500.html", _assigns) do
7
+  #   "Internal Server Error"
8
+  # end
9
+
10
+  # By default, Phoenix returns the status message from
11
+  # the template name. For example, "404.html" becomes
12
+  # "Not Found".
13
+  def template_not_found(template, _assigns) do
14
+    Phoenix.Controller.status_message_from_template(template)
15
+  end
16
+end

+ 3
- 0
lib/koype_publish_web/views/layout_view.ex View File

@@ -0,0 +1,3 @@
1
+defmodule Koype.PublishWeb.LayoutView do
2
+  use Koype.PublishWeb, :view
3
+end

+ 3
- 0
lib/koype_publish_web/views/page_view.ex View File

@@ -0,0 +1,3 @@
1
+defmodule Koype.PublishWeb.PageView do
2
+  use Koype.PublishWeb, :view
3
+end

+ 62
- 0
mix.exs View File

@@ -0,0 +1,62 @@
1
+defmodule Koype.Publish.MixProject do
2
+  use Mix.Project
3
+
4
+  def project do
5
+    [
6
+      app: :koype_publish,
7
+      version: "0.1.0",
8
+      elixir: "~> 1.5",
9
+      elixirc_paths: elixirc_paths(Mix.env()),
10
+      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
11
+      start_permanent: Mix.env() == :prod,
12
+      aliases: aliases(),
13
+      deps: deps()
14
+    ]
15
+  end
16
+
17
+  # Configuration for the OTP application.
18
+  #
19
+  # Type `mix help compile.app` for more information.
20
+  def application do
21
+    [
22
+      mod: {Koype.Publish.Application, []},
23
+      extra_applications: [:logger, :runtime_tools]
24
+    ]
25
+  end
26
+
27
+  # Specifies which paths to compile per environment.
28
+  defp elixirc_paths(:test), do: ["lib", "test/support"]
29
+  defp elixirc_paths(_), do: ["lib"]
30
+
31
+  # Specifies your project dependencies.
32
+  #
33
+  # Type `mix help deps` for examples and options.
34
+  defp deps do
35
+    [
36
+      {:phoenix, "~> 1.4.0"},
37
+      {:phoenix_pubsub, "~> 1.1"},
38
+      {:phoenix_ecto, "~> 4.0"},
39
+      {:ecto_sql, "~> 3.0"},
40
+      {:postgrex, ">= 0.0.0"},
41
+      {:phoenix_html, "~> 2.11"},
42
+      {:phoenix_live_reload, "~> 1.2", only: :dev},
43
+      {:gettext, "~> 0.11"},
44
+      {:jason, "~> 1.0"},
45
+      {:plug_cowboy, "~> 2.0"}
46
+    ]
47
+  end
48
+
49
+  # Aliases are shortcuts or tasks specific to the current project.
50
+  # For example, to create, migrate and run the seeds file at once:
51
+  #
52
+  #     $ mix ecto.setup
53
+  #
54
+  # See the documentation for `Mix` for more info on aliases.
55
+  defp aliases do
56
+    [
57
+      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
58
+      "ecto.reset": ["ecto.drop", "ecto.setup"],
59
+      test: ["ecto.create --quiet", "ecto.migrate", "test"]
60
+    ]
61
+  end
62
+end

+ 24
- 0
mix.lock View File

@@ -0,0 +1,24 @@
1
+%{
2
+  "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
3
+  "cowboy": {:hex, :cowboy, "2.6.1", "f2e06f757c337b3b311f9437e6e072b678fcd71545a7b2865bdaa154d078593f", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
4
+  "cowlib": {:hex, :cowlib, "2.7.0", "3ef16e77562f9855a2605900cedb15c1462d76fb1be6a32fc3ae91973ee543d2", [:rebar3], [], "hexpm"},
5
+  "db_connection": {:hex, :db_connection, "2.0.3", "b4e8aa43c100e16f122ccd6798cd51c48c79fd391c39d411f42b3cd765daccb0", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
6
+  "decimal": {:hex, :decimal, "1.6.0", "bfd84d90ff966e1f5d4370bdd3943432d8f65f07d3bab48001aebd7030590dcc", [:mix], [], "hexpm"},
7
+  "ecto": {:hex, :ecto, "3.0.6", "d33ab5b3f7553a41507d4b0ad5bf192d533119c4ad08f3a5d63d85aa12117dc9", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
8
+  "ecto_sql": {:hex, :ecto_sql, "3.0.4", "e7a0feb0b2484b90981c56d5cd03c52122c1c31ded0b95ed213b7c5c07ae6737", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0.6", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.3.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
9
+  "file_system": {:hex, :file_system, "0.2.6", "fd4dc3af89b9ab1dc8ccbcc214a0e60c41f34be251d9307920748a14bf41f1d3", [:mix], [], "hexpm"},
10
+  "gettext": {:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2", [:mix], [], "hexpm"},
11
+  "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
12
+  "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
13
+  "phoenix": {:hex, :phoenix, "1.4.0", "56fe9a809e0e735f3e3b9b31c1b749d4b436e466d8da627b8d82f90eaae714d2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
14
+  "phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
15
+  "phoenix_html": {:hex, :phoenix_html, "2.13.0", "3bad10de5efb6c590f7aa5b316ad0d3faa054715414c9b562c410de4ffb885c5", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
16
+  "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.0", "3bb31a9fbd40ffe8652e60c8660dffd72dd231efcdf49b744fb75b9ef7db5dd2", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
17
+  "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.1", "6668d787e602981f24f17a5fbb69cc98f8ab085114ebfac6cc36e10a90c8e93c", [:mix], [], "hexpm"},
18
+  "plug": {:hex, :plug, "1.7.1", "8516d565fb84a6a8b2ca722e74e2cd25ca0fc9d64f364ec9dbec09d33eb78ccd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}], "hexpm"},
19
+  "plug_cowboy": {:hex, :plug_cowboy, "2.0.1", "d798f8ee5acc86b7d42dbe4450b8b0dadf665ce588236eb0a751a132417a980e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
20
+  "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
21
+  "postgrex": {:hex, :postgrex, "0.14.1", "63247d4a5ad6b9de57a0bac5d807e1c32d41e39c04b8a4156a26c63bcd8a2e49", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
22
+  "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
23
+  "telemetry": {:hex, :telemetry, "0.3.0", "099a7f3ce31e4780f971b4630a3c22ec66d22208bc090fe33a2a3a6a67754a73", [:rebar3], [], "hexpm"},
24
+}

+ 97
- 0
priv/gettext/en/LC_MESSAGES/errors.po View File

@@ -0,0 +1,97 @@
1
+## `msgid`s in this file come from POT (.pot) files.
2
+##
3
+## Do not add, change, or remove `msgid`s manually here as
4
+## they're tied to the ones in the corresponding POT file
5
+## (with the same domain).
6
+##
7
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
8
+## to merge POT files into PO files.
9
+msgid ""
10
+msgstr ""
11
+"Language: en\n"
12
+
13
+## From Ecto.Changeset.cast/4
14
+msgid "can't be blank"
15
+msgstr ""
16
+
17
+## From Ecto.Changeset.unique_constraint/3
18
+msgid "has already been taken"
19
+msgstr ""
20
+
21
+## From Ecto.Changeset.put_change/3
22
+msgid "is invalid"
23
+msgstr ""
24
+
25
+## From Ecto.Changeset.validate_acceptance/3
26
+msgid "must be accepted"
27
+msgstr ""
28
+
29
+## From Ecto.Changeset.validate_format/3
30
+msgid "has invalid format"
31
+msgstr ""
32
+
33
+## From Ecto.Changeset.validate_subset/3
34
+msgid "has an invalid entry"
35
+msgstr ""
36
+
37
+## From Ecto.Changeset.validate_exclusion/3
38
+msgid "is reserved"
39
+msgstr ""
40
+
41
+## From Ecto.Changeset.validate_confirmation/3
42
+msgid "does not match confirmation"
43
+msgstr ""
44
+
45
+## From Ecto.Changeset.no_assoc_constraint/3
46
+msgid "is still associated with this entry"
47
+msgstr ""
48
+
49
+msgid "are still associated with this entry"
50
+msgstr ""
51
+
52
+## From Ecto.Changeset.validate_length/3
53
+msgid "should be %{count} character(s)"
54
+msgid_plural "should be %{count} character(s)"
55
+msgstr[0] ""
56
+msgstr[1] ""
57
+
58
+msgid "should have %{count} item(s)"
59
+msgid_plural "should have %{count} item(s)"
60
+msgstr[0] ""
61
+msgstr[1] ""
62
+
63
+msgid "should be at least %{count} character(s)"
64
+msgid_plural "should be at least %{count} character(s)"
65
+msgstr[0] ""
66
+msgstr[1] ""
67
+
68
+msgid "should have at least %{count} item(s)"
69
+msgid_plural "should have at least %{count} item(s)"
70
+msgstr[0] ""
71
+msgstr[1] ""
72
+
73
+msgid "should be at most %{count} character(s)"
74
+msgid_plural "should be at most %{count} character(s)"
75
+msgstr[0] ""
76
+msgstr[1] ""
77
+
78
+msgid "should have at most %{count} item(s)"
79
+msgid_plural "should have at most %{count} item(s)"
80
+msgstr[0] ""
81
+msgstr[1] ""
82
+
83
+## From Ecto.Changeset.validate_number/3
84
+msgid "must be less than %{number}"
85
+msgstr ""
86
+
87
+msgid "must be greater than %{number}"
88
+msgstr ""
89
+
90
+msgid "must be less than or equal to %{number}"
91
+msgstr ""
92
+
93
+msgid "must be greater than or equal to %{number}"
94
+msgstr ""
95
+
96
+msgid "must be equal to %{number}"
97
+msgstr ""

+ 95
- 0
priv/gettext/errors.pot View File

@@ -0,0 +1,95 @@
1
+## This is a PO Template file.
2
+##
3
+## `msgid`s here are often extracted from source code.
4
+## Add new translations manually only if they're dynamic
5
+## translations that can't be statically extracted.
6
+##
7
+## Run `mix gettext.extract` to bring this file up to
8
+## date. Leave `msgstr`s empty as changing them here has no
9
+## effect: edit them in PO (`.po`) files instead.
10
+
11
+## From Ecto.Changeset.cast/4
12
+msgid "can't be blank"
13
+msgstr ""
14
+
15
+## From Ecto.Changeset.unique_constraint/3
16
+msgid "has already been taken"
17
+msgstr ""
18
+
19
+## From Ecto.Changeset.put_change/3
20
+msgid "is invalid"
21
+msgstr ""
22
+
23
+## From Ecto.Changeset.validate_acceptance/3
24
+msgid "must be accepted"
25
+msgstr ""
26
+
27
+## From Ecto.Changeset.validate_format/3
28
+msgid "has invalid format"
29
+msgstr ""
30
+
31
+## From Ecto.Changeset.validate_subset/3
32
+msgid "has an invalid entry"
33
+msgstr ""
34
+
35
+## From Ecto.Changeset.validate_exclusion/3
36
+msgid "is reserved"
37
+msgstr ""
38
+
39
+## From Ecto.Changeset.validate_confirmation/3
40
+msgid "does not match confirmation"
41
+msgstr ""
42
+
43
+## From Ecto.Changeset.no_assoc_constraint/3
44
+msgid "is still associated with this entry"
45
+msgstr ""
46
+
47
+msgid "are still associated with this entry"
48
+msgstr ""
49
+
50
+## From Ecto.Changeset.validate_length/3
51
+msgid "should be %{count} character(s)"
52
+msgid_plural "should be %{count} character(s)"
53
+msgstr[0] ""
54
+msgstr[1] ""
55
+
56
+msgid "should have %{count} item(s)"
57
+msgid_plural "should have %{count} item(s)"
58
+msgstr[0] ""
59
+msgstr[1] ""
60
+
61
+msgid "should be at least %{count} character(s)"
62
+msgid_plural "should be at least %{count} character(s)"
63
+msgstr[0] ""
64
+msgstr[1] ""
65
+
66
+msgid "should have at least %{count} item(s)"
67
+msgid_plural "should have at least %{count} item(s)"
68
+msgstr[0] ""
69
+msgstr[1] ""
70
+
71
+msgid "should be at most %{count} character(s)"
72
+msgid_plural "should be at most %{count} character(s)"
73
+msgstr[0] ""
74
+msgstr[1] ""
75
+
76
+msgid "should have at most %{count} item(s)"
77
+msgid_plural "should have at most %{count} item(s)"
78
+msgstr[0] ""
79
+msgstr[1] ""
80
+
81
+## From Ecto.Changeset.validate_number/3
82
+msgid "must be less than %{number}"
83
+msgstr ""
84
+
85
+msgid "must be greater than %{number}"
86
+msgstr ""
87
+
88
+msgid "must be less than or equal to %{number}"
89
+msgstr ""
90
+
91
+msgid "must be greater than or equal to %{number}"
92
+msgstr ""
93
+
94
+msgid "must be equal to %{number}"
95
+msgstr ""

+ 4
- 0
priv/repo/migrations/.formatter.exs View File

@@ -0,0 +1,4 @@
1
+[
2
+  import_deps: [:ecto_sql],
3
+  inputs: ["*.exs"]
4
+]

+ 11
- 0
priv/repo/seeds.exs View File

@@ -0,0 +1,11 @@
1
+# Script for populating the database. You can run it as:
2
+#
3
+#     mix run priv/repo/seeds.exs
4
+#
5
+# Inside the script, you can read and write to any of your
6
+# repositories directly:
7
+#
8
+#     Koype.Publish.Repo.insert!(%Koype.Publish.SomeSchema{})
9
+#
10
+# We recommend using the bang functions (`insert!`, `update!`
11
+# and so on) as they will fail if something goes wrong.

+ 8
- 0
test/koype_publish_web/controllers/page_controller_test.exs View File

@@ -0,0 +1,8 @@
1
+defmodule Koype.PublishWeb.PageControllerTest do
2
+  use Koype.PublishWeb.ConnCase
3
+
4
+  test "GET /", %{conn: conn} do
5
+    conn = get(conn, "/")
6
+    assert html_response(conn, 200) =~ "Welcome to Phoenix!"
7
+  end
8
+end

+ 14
- 0
test/koype_publish_web/views/error_view_test.exs View File

@@ -0,0 +1,14 @@
1
+defmodule Koype.PublishWeb.ErrorViewTest do
2
+  use Koype.PublishWeb.ConnCase, async: true
3
+
4
+  # Bring render/3 and render_to_string/3 for testing custom views
5
+  import Phoenix.View
6
+
7
+  test "renders 404.html" do
8
+    assert render_to_string(Koype.PublishWeb.ErrorView, "404.html", []) == "Not Found"
9
+  end
10
+
11
+  test "renders 500.html" do
12
+    assert render_to_string(Koype.PublishWeb.ErrorView, "500.html", []) == "Internal Server Error"
13
+  end
14
+end

+ 3
- 0
test/koype_publish_web/views/layout_view_test.exs View File

@@ -0,0 +1,3 @@
1
+defmodule Koype.PublishWeb.LayoutViewTest do
2
+  use Koype.PublishWeb.ConnCase, async: true
3
+end

+ 3
- 0
test/koype_publish_web/views/page_view_test.exs View File

@@ -0,0 +1,3 @@
1
+defmodule Koype.PublishWeb.PageViewTest do
2
+  use Koype.PublishWeb.ConnCase, async: true
3
+end

+ 37
- 0
test/support/channel_case.ex View File

@@ -0,0 +1,37 @@
1
+defmodule Koype.PublishWeb.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
+  it cannot be async. For this reason, every test runs
12
+  inside a transaction which is reset at the beginning
13
+  of the test unless the test case is marked as async.
14
+  """
15
+
16
+  use ExUnit.CaseTemplate
17
+
18
+  using do
19
+    quote do
20
+      # Import conveniences for testing with channels
21
+      use Phoenix.ChannelTest
22
+
23
+      # The default endpoint for testing
24
+      @endpoint Koype.PublishWeb.Endpoint
25
+    end
26
+  end
27
+
28
+  setup tags do
29
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Koype.Publish.Repo)
30
+
31
+    unless tags[:async] do
32
+      Ecto.Adapters.SQL.Sandbox.mode(Koype.Publish.Repo, {:shared, self()})
33
+    end
34
+
35
+    :ok
36
+  end
37
+end

+ 38
- 0
test/support/conn_case.ex View File

@@ -0,0 +1,38 @@
1
+defmodule Koype.PublishWeb.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
+  it cannot be async. For this reason, every test runs
12
+  inside a transaction which is reset at the beginning
13
+  of the test unless the test case is marked as async.
14
+  """
15
+
16
+  use ExUnit.CaseTemplate
17
+
18
+  using do
19
+    quote do
20
+      # Import conveniences for testing with connections
21
+      use Phoenix.ConnTest
22
+      alias Koype.PublishWeb.Router.Helpers, as: Routes
23
+
24
+      # The default endpoint for testing
25
+      @endpoint Koype.PublishWeb.Endpoint
26
+    end
27
+  end
28
+
29
+  setup tags do
30
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Koype.Publish.Repo)
31
+
32
+    unless tags[:async] do
33
+      Ecto.Adapters.SQL.Sandbox.mode(Koype.Publish.Repo, {:shared, self()})
34
+    end
35
+
36
+    {:ok, conn: Phoenix.ConnTest.build_conn()}
37
+  end
38
+end

+ 53
- 0
test/support/data_case.ex View File

@@ -0,0 +1,53 @@
1
+defmodule Koype.Publish.DataCase do
2
+  @moduledoc """
3
+  This module defines the setup for tests requiring
4
+  access to the application's data layer.
5
+
6
+  You may define functions here to be used as helpers in
7
+  your tests.
8
+
9
+  Finally, if the test case interacts with the database,
10
+  it cannot be async. For this reason, every test runs
11
+  inside a transaction which is reset at the beginning
12
+  of the test unless the test case is marked as async.
13
+  """
14
+
15
+  use ExUnit.CaseTemplate
16
+
17
+  using do
18
+    quote do
19
+      alias Koype.Publish.Repo
20
+
21
+      import Ecto
22
+      import Ecto.Changeset
23
+      import Ecto.Query
24
+      import Koype.Publish.DataCase
25
+    end
26
+  end
27
+
28
+  setup tags do
29
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Koype.Publish.Repo)
30
+
31
+    unless tags[:async] do
32
+      Ecto.Adapters.SQL.Sandbox.mode(Koype.Publish.Repo, {:shared, self()})
33
+    end
34
+
35
+    :ok
36
+  end
37
+
38
+  @doc """
39
+  A helper that transforms changeset errors into a map of messages.
40
+
41
+      assert {:error, changeset} = Accounts.create_user(%{password: "short"})
42
+      assert "password is too short" in errors_on(changeset).password
43
+      assert %{password: ["password is too short"]} = errors_on(changeset)
44
+
45
+  """
46
+  def errors_on(changeset) do
47
+    Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
48
+      Enum.reduce(opts, message, fn {key, value}, acc ->
49
+        String.replace(acc, "%{#{key}}", to_string(value))
50
+      end)
51
+    end)
52
+  end
53
+end

+ 2
- 0
test/test_helper.exs View File

@@ -0,0 +1,2 @@
1
+ExUnit.start()
2
+Ecto.Adapters.SQL.Sandbox.mode(Koype.Publish.Repo, :manual)

Loading…
Cancel
Save