forked from shibao/cannery
		
	update to phoenix 1.6
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -25,7 +25,7 @@ cannery-*.tar | |||||||
| # If NPM crashes, it generates a log, let's ignore it too. | # If NPM crashes, it generates a log, let's ignore it too. | ||||||
| npm-debug.log | npm-debug.log | ||||||
|  |  | ||||||
| # The directory NPM downloads your dependencies sources to. | # Ignore assets that are produced by build tools. | ||||||
| /assets/node_modules/ | /assets/node_modules/ | ||||||
|  |  | ||||||
| # Since we are building assets from assets/, | # Since we are building assets from assets/, | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| # Cannery is a personal ammo manager that adjusts to your own needs. | # Cannery is a personal ammo manager that adjusts to your own needs. | ||||||
|  |  | ||||||
| * Easy to Use: Cannery lets you easily keep an eye on your ammo levels after range day | * Easy to Use: Cannery lets you easily keep an eye on your ammo levels before and after range day | ||||||
| * Secure: Self-host your own instance, or use an instance from someone you trust. | * Secure: Self-host your own instance, or use an instance from someone you trust. | ||||||
| * Simple: Access from any internet-capable device | * Simple: Access from any internet-capable device | ||||||
| @@ -10,25 +10,7 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts"; | |||||||
|  |  | ||||||
| @import "components"; | @import "components"; | ||||||
|  |  | ||||||
| /* LiveView specific classes for your customizations */ | /* Alerts and form errors used by phx.new */ | ||||||
| .phx-no-feedback.invalid-feedback, |  | ||||||
| .phx-no-feedback .invalid-feedback { |  | ||||||
|   display: none; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .phx-click-loading { |  | ||||||
|   opacity: 0.5; |  | ||||||
|   transition: opacity 1s ease-out; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .phx-disconnected{ |  | ||||||
|   cursor: wait; |  | ||||||
| } |  | ||||||
| .phx-disconnected *{ |  | ||||||
|   pointer-events: none; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Alerts and form errors */ |  | ||||||
| .alert { | .alert { | ||||||
|   padding: 15px; |   padding: 15px; | ||||||
|   margin-bottom: 20px; |   margin-bottom: 20px; | ||||||
| @@ -61,3 +43,87 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts"; | |||||||
|   display: block; |   display: block; | ||||||
|   margin: -1rem 0 2rem; |   margin: -1rem 0 2rem; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* LiveView specific classes for your customization */ | ||||||
|  | .phx-no-feedback.invalid-feedback, | ||||||
|  | .phx-no-feedback .invalid-feedback { | ||||||
|  |   display: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-click-loading { | ||||||
|  |   opacity: 0.5; | ||||||
|  |   transition: opacity 1s ease-out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-loading{ | ||||||
|  |   cursor: wait; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-modal { | ||||||
|  |   opacity: 1!important; | ||||||
|  |   position: fixed; | ||||||
|  |   z-index: 1; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   overflow: auto; | ||||||
|  |   background-color: rgba(0,0,0,0.4); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-modal-content { | ||||||
|  |   background-color: #fefefe; | ||||||
|  |   margin: 15vh auto; | ||||||
|  |   padding: 20px; | ||||||
|  |   border: 1px solid #888; | ||||||
|  |   width: 80%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-modal-close { | ||||||
|  |   color: #aaa; | ||||||
|  |   float: right; | ||||||
|  |   font-size: 28px; | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .phx-modal-close:hover, | ||||||
|  | .phx-modal-close:focus { | ||||||
|  |   color: black; | ||||||
|  |   text-decoration: none; | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .fade-in-scale { | ||||||
|  |   animation: 0.2s ease-in 0s normal forwards 1 fade-in-scale-keys; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .fade-out-scale { | ||||||
|  |   animation: 0.2s ease-out 0s normal forwards 1 fade-out-scale-keys; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .fade-in { | ||||||
|  |   animation: 0.2s ease-out 0s normal forwards 1 fade-in-keys; | ||||||
|  | } | ||||||
|  | .fade-out { | ||||||
|  |   animation: 0.2s ease-out 0s normal forwards 1 fade-out-keys; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @keyframes fade-in-scale-keys{ | ||||||
|  |   0% { scale: 0.95; opacity: 0; } | ||||||
|  |   100% { scale: 1.0; opacity: 1; } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @keyframes fade-out-scale-keys{ | ||||||
|  |   0% { scale: 1.0; opacity: 1; } | ||||||
|  |   100% { scale: 0.95; opacity: 0; } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @keyframes fade-in-keys{ | ||||||
|  |   0% { opacity: 0; } | ||||||
|  |   100% { opacity: 1; } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @keyframes fade-out-keys{ | ||||||
|  |   0% { opacity: 1; } | ||||||
|  |   100% { opacity: 0; } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,31 +1,33 @@ | |||||||
| // We need to import the CSS so that webpack will load it. | // We import the CSS which is extracted to its own file by esbuild. | ||||||
| // The MiniCssExtractPlugin is used to separate it out into | // Remove this line if you add a your own CSS build pipeline (e.g postcss). | ||||||
| // its own CSS file. |  | ||||||
| import "../css/app.scss" | import "../css/app.scss" | ||||||
|  |  | ||||||
| // webpack automatically bundles all modules in your | // If you want to use Phoenix channels, run `mix help phx.gen.channel` | ||||||
| // entry points. Those entry points can be configured | // to get started and then uncomment the line below. | ||||||
| // in "webpack.config.js". | // import "./user_socket.js" | ||||||
| // |  | ||||||
| // Import deps with the dep name or local files with a relative path, for example: |  | ||||||
| // |  | ||||||
| //     import {Socket} from "phoenix" |  | ||||||
| //     import socket from "./socket" |  | ||||||
| // |  | ||||||
| import "phoenix_html" |  | ||||||
| import {Socket} from "phoenix" |  | ||||||
| import topbar from "topbar" |  | ||||||
| import {LiveSocket} from "phoenix_live_view" |  | ||||||
|  |  | ||||||
| let Hooks = {}; | // You can include dependencies in two ways. | ||||||
| Hooks.MaintainAttrs = { | // | ||||||
|   attrs(){ return this.el.getAttribute("data-attrs").split(", ") }, | // The simplest option is to put them in assets/vendor and | ||||||
|   beforeUpdate(){ this.prevAttrs = this.attrs().map(name => [name, this.el.getAttribute(name)]) }, | // import them using relative paths: | ||||||
|   updated(){ this.prevAttrs.forEach(([name, val]) => this.el.setAttribute(name, val)) } | // | ||||||
| }; | //     import "../vendor/some-package.js" | ||||||
|  | // | ||||||
|  | // Alternatively, you can `npm install some-package --prefix assets` and import | ||||||
|  | // them using a path starting with the package name: | ||||||
|  | // | ||||||
|  | //     import "some-package" | ||||||
|  | // | ||||||
|  |  | ||||||
|  | // Include phoenix_html to handle method=PUT/DELETE in forms and buttons. | ||||||
|  | import "phoenix_html" | ||||||
|  | // Establish Phoenix Socket and LiveView configuration. | ||||||
|  | import {Socket} from "phoenix" | ||||||
|  | import {LiveSocket} from "phoenix_live_view" | ||||||
|  | import topbar from "../vendor/topbar" | ||||||
|  |  | ||||||
| let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") | let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") | ||||||
| let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, params: {_csrf_token: csrfToken}}) | let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) | ||||||
|  |  | ||||||
| // Show progress bar on live navigation and form submits | // Show progress bar on live navigation and form submits | ||||||
| topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) | topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) | ||||||
| @@ -40,4 +42,3 @@ liveSocket.connect() | |||||||
| // >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session | // >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session | ||||||
| // >> liveSocket.disableLatencySim() | // >> liveSocket.disableLatencySim() | ||||||
| window.liveSocket = liveSocket | window.liveSocket = liveSocket | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,63 +0,0 @@ | |||||||
| // NOTE: The contents of this file will only be executed if |  | ||||||
| // you uncomment its entry in "assets/js/app.js". |  | ||||||
|  |  | ||||||
| // To use Phoenix channels, the first step is to import Socket, |  | ||||||
| // and connect at the socket path in "lib/web/endpoint.ex". |  | ||||||
| // |  | ||||||
| // Pass the token on params as below. Or remove it |  | ||||||
| // from the params if you are not using authentication. |  | ||||||
| import {Socket} from "phoenix" |  | ||||||
|  |  | ||||||
| let socket = new Socket("/socket", {params: {token: window.userToken}}) |  | ||||||
|  |  | ||||||
| // When you connect, you'll often need to authenticate the client. |  | ||||||
| // For example, imagine you have an authentication plug, `MyAuth`, |  | ||||||
| // which authenticates the session and assigns a `:current_user`. |  | ||||||
| // If the current user exists you can assign the user's token in |  | ||||||
| // the connection for use in the layout. |  | ||||||
| // |  | ||||||
| // In your "lib/web/router.ex": |  | ||||||
| // |  | ||||||
| //     pipeline :browser do |  | ||||||
| //       ... |  | ||||||
| //       plug MyAuth |  | ||||||
| //       plug :put_user_token |  | ||||||
| //     end |  | ||||||
| // |  | ||||||
| //     defp put_user_token(conn, _) do |  | ||||||
| //       if current_user = conn.assigns[:current_user] do |  | ||||||
| //         token = Phoenix.Token.sign(conn, "user socket", current_user.id) |  | ||||||
| //         assign(conn, :user_token, token) |  | ||||||
| //       else |  | ||||||
| //         conn |  | ||||||
| //       end |  | ||||||
| //     end |  | ||||||
| // |  | ||||||
| // Now you need to pass this token to JavaScript. You can do so |  | ||||||
| // inside a script tag in "lib/web/templates/layout/app.html.eex": |  | ||||||
| // |  | ||||||
| //     <script>window.userToken = "<%= assigns[:user_token] %>";</script> |  | ||||||
| // |  | ||||||
| // You will need to verify the user token in the "connect/3" function |  | ||||||
| // in "lib/web/channels/user_socket.ex": |  | ||||||
| // |  | ||||||
| //     def connect(%{"token" => token}, socket, _connect_info) do |  | ||||||
| //       # max_age: 1209600 is equivalent to two weeks in seconds |  | ||||||
| //       case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do |  | ||||||
| //         {:ok, user_id} -> |  | ||||||
| //           {:ok, socket |> assign(:user, user_id)} |  | ||||||
| //         {:error, reason} -> |  | ||||||
| //           :error |  | ||||||
| //       end |  | ||||||
| //     end |  | ||||||
| // |  | ||||||
| // Finally, connect to the socket: |  | ||||||
| socket.connect() |  | ||||||
|  |  | ||||||
| // Now that you are connected, you can join channels with a topic: |  | ||||||
| let channel = socket.channel("topic:subtopic", {}) |  | ||||||
| channel.join() |  | ||||||
|   .receive("ok", resp => { console.log("Joined successfully", resp) }) |  | ||||||
|   .receive("error", resp => { console.log("Unable to join", resp) }) |  | ||||||
|  |  | ||||||
| export default socket |  | ||||||
							
								
								
									
										88
									
								
								assets/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										88
									
								
								assets/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1109,9 +1109,9 @@ | |||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "@types/eslint": { |     "@types/eslint": { | ||||||
|       "version": "7.28.0", |       "version": "8.4.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", |       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.0.tgz", | ||||||
|       "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", |       "integrity": "sha512-JUYa/5JwoqikCy7O7jKtuNe9Z4ZZt615G+1EKfaDGSNEpzaA2OwbV/G1v08Oa7fd1XzlFoSCvt9ePl9/6FyAug==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@types/estree": "*", |         "@types/estree": "*", | ||||||
| @@ -1119,9 +1119,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "@types/eslint-scope": { |     "@types/eslint-scope": { | ||||||
|       "version": "3.7.1", |       "version": "3.7.3", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", |       "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", | ||||||
|       "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", |       "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@types/eslint": "*", |         "@types/eslint": "*", | ||||||
| @@ -1382,9 +1382,9 @@ | |||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "acorn-import-assertions": { |     "acorn-import-assertions": { | ||||||
|       "version": "1.7.6", |       "version": "1.8.0", | ||||||
|       "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", |       "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", | ||||||
|       "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", |       "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "acorn-node": { |     "acorn-node": { | ||||||
| @@ -3190,9 +3190,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "enhanced-resolve": { |     "enhanced-resolve": { | ||||||
|       "version": "5.8.2", |       "version": "5.8.3", | ||||||
|       "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", |       "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", | ||||||
|       "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", |       "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "graceful-fs": "^4.2.4", |         "graceful-fs": "^4.2.4", | ||||||
| @@ -3200,9 +3200,9 @@ | |||||||
|       }, |       }, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "tapable": { |         "tapable": { | ||||||
|           "version": "2.2.0", |           "version": "2.2.1", | ||||||
|           "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", |           "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", | ||||||
|           "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", |           "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -3244,9 +3244,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "es-module-lexer": { |     "es-module-lexer": { | ||||||
|       "version": "0.7.1", |       "version": "0.9.3", | ||||||
|       "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", |       "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", | ||||||
|       "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", |       "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "escalade": { |     "escalade": { | ||||||
| @@ -3287,9 +3287,9 @@ | |||||||
|       }, |       }, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "estraverse": { |         "estraverse": { | ||||||
|           "version": "5.2.0", |           "version": "5.3.0", | ||||||
|           "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", |           "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", | ||||||
|           "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", |           "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -9401,9 +9401,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "watchpack": { |     "watchpack": { | ||||||
|       "version": "2.2.0", |       "version": "2.3.1", | ||||||
|       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", |       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", | ||||||
|       "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", |       "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "glob-to-regexp": "^0.4.1", |         "glob-to-regexp": "^0.4.1", | ||||||
| @@ -9420,9 +9420,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "webpack": { |     "webpack": { | ||||||
|       "version": "5.50.0", |       "version": "5.67.0", | ||||||
|       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.50.0.tgz", |       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.67.0.tgz", | ||||||
|       "integrity": "sha512-hqxI7t/KVygs0WRv/kTgUW8Kl3YC81uyWQSo/7WUs5LsuRw0htH/fCwbVBGCuiX/t4s7qzjXFcf41O8Reiypag==", |       "integrity": "sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@types/eslint-scope": "^3.7.0", |         "@types/eslint-scope": "^3.7.0", | ||||||
| @@ -9434,12 +9434,12 @@ | |||||||
|         "acorn-import-assertions": "^1.7.6", |         "acorn-import-assertions": "^1.7.6", | ||||||
|         "browserslist": "^4.14.5", |         "browserslist": "^4.14.5", | ||||||
|         "chrome-trace-event": "^1.0.2", |         "chrome-trace-event": "^1.0.2", | ||||||
|         "enhanced-resolve": "^5.8.0", |         "enhanced-resolve": "^5.8.3", | ||||||
|         "es-module-lexer": "^0.7.1", |         "es-module-lexer": "^0.9.0", | ||||||
|         "eslint-scope": "5.1.1", |         "eslint-scope": "5.1.1", | ||||||
|         "events": "^3.2.0", |         "events": "^3.2.0", | ||||||
|         "glob-to-regexp": "^0.4.1", |         "glob-to-regexp": "^0.4.1", | ||||||
|         "graceful-fs": "^4.2.4", |         "graceful-fs": "^4.2.9", | ||||||
|         "json-parse-better-errors": "^1.0.2", |         "json-parse-better-errors": "^1.0.2", | ||||||
|         "loader-runner": "^4.2.0", |         "loader-runner": "^4.2.0", | ||||||
|         "mime-types": "^2.1.27", |         "mime-types": "^2.1.27", | ||||||
| @@ -9447,14 +9447,20 @@ | |||||||
|         "schema-utils": "^3.1.0", |         "schema-utils": "^3.1.0", | ||||||
|         "tapable": "^2.1.1", |         "tapable": "^2.1.1", | ||||||
|         "terser-webpack-plugin": "^5.1.3", |         "terser-webpack-plugin": "^5.1.3", | ||||||
|         "watchpack": "^2.2.0", |         "watchpack": "^2.3.1", | ||||||
|         "webpack-sources": "^3.2.0" |         "webpack-sources": "^3.2.3" | ||||||
|       }, |       }, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "acorn": { |         "acorn": { | ||||||
|           "version": "8.4.1", |           "version": "8.7.0", | ||||||
|           "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", |           "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", | ||||||
|           "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", |           "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|  |         "graceful-fs": { | ||||||
|  |           "version": "4.2.9", | ||||||
|  |           "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", | ||||||
|  |           "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|         "schema-utils": { |         "schema-utils": { | ||||||
| @@ -9469,15 +9475,15 @@ | |||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "tapable": { |         "tapable": { | ||||||
|           "version": "2.2.0", |           "version": "2.2.1", | ||||||
|           "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", |           "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", | ||||||
|           "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", |           "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|         "webpack-sources": { |         "webpack-sources": { | ||||||
|           "version": "3.2.0", |           "version": "3.2.3", | ||||||
|           "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", |           "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", | ||||||
|           "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", |           "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
|     "style-loader": "^3.2.1", |     "style-loader": "^3.2.1", | ||||||
|     "tailwindcss": "^2.2.7", |     "tailwindcss": "^2.2.7", | ||||||
|     "terser-webpack-plugin": "^5.1.3", |     "terser-webpack-plugin": "^5.1.3", | ||||||
|     "webpack": "^5.50.0", |     "webpack": "^5.67.0", | ||||||
|     "webpack-cli": "^4.8.0", |     "webpack-cli": "^4.8.0", | ||||||
|     "webpack-dev-server": "^3.11.2" |     "webpack-dev-server": "^3.11.2" | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file | ||||||
| # | # | ||||||
| # To ban all spiders from the entire site uncomment the next two lines: | # To ban all spiders from the entire site uncomment the next two lines: | ||||||
| # User-agent: * | # User-agent: * | ||||||
|   | |||||||
							
								
								
									
										157
									
								
								assets/vendor/topbar.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								assets/vendor/topbar.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | |||||||
|  | /** | ||||||
|  |  * @license MIT | ||||||
|  |  * topbar 1.0.0, 2021-01-06 | ||||||
|  |  * https://buunguyen.github.io/topbar | ||||||
|  |  * Copyright (c) 2021 Buu Nguyen | ||||||
|  |  */ | ||||||
|  | (function (window, document) { | ||||||
|  |   "use strict"; | ||||||
|  |  | ||||||
|  |   // https://gist.github.com/paulirish/1579671 | ||||||
|  |   (function () { | ||||||
|  |     var lastTime = 0; | ||||||
|  |     var vendors = ["ms", "moz", "webkit", "o"]; | ||||||
|  |     for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { | ||||||
|  |       window.requestAnimationFrame = | ||||||
|  |         window[vendors[x] + "RequestAnimationFrame"]; | ||||||
|  |       window.cancelAnimationFrame = | ||||||
|  |         window[vendors[x] + "CancelAnimationFrame"] || | ||||||
|  |         window[vendors[x] + "CancelRequestAnimationFrame"]; | ||||||
|  |     } | ||||||
|  |     if (!window.requestAnimationFrame) | ||||||
|  |       window.requestAnimationFrame = function (callback, element) { | ||||||
|  |         var currTime = new Date().getTime(); | ||||||
|  |         var timeToCall = Math.max(0, 16 - (currTime - lastTime)); | ||||||
|  |         var id = window.setTimeout(function () { | ||||||
|  |           callback(currTime + timeToCall); | ||||||
|  |         }, timeToCall); | ||||||
|  |         lastTime = currTime + timeToCall; | ||||||
|  |         return id; | ||||||
|  |       }; | ||||||
|  |     if (!window.cancelAnimationFrame) | ||||||
|  |       window.cancelAnimationFrame = function (id) { | ||||||
|  |         clearTimeout(id); | ||||||
|  |       }; | ||||||
|  |   })(); | ||||||
|  |  | ||||||
|  |   var canvas, | ||||||
|  |     progressTimerId, | ||||||
|  |     fadeTimerId, | ||||||
|  |     currentProgress, | ||||||
|  |     showing, | ||||||
|  |     addEvent = function (elem, type, handler) { | ||||||
|  |       if (elem.addEventListener) elem.addEventListener(type, handler, false); | ||||||
|  |       else if (elem.attachEvent) elem.attachEvent("on" + type, handler); | ||||||
|  |       else elem["on" + type] = handler; | ||||||
|  |     }, | ||||||
|  |     options = { | ||||||
|  |       autoRun: true, | ||||||
|  |       barThickness: 3, | ||||||
|  |       barColors: { | ||||||
|  |         0: "rgba(26,  188, 156, .9)", | ||||||
|  |         ".25": "rgba(52,  152, 219, .9)", | ||||||
|  |         ".50": "rgba(241, 196, 15,  .9)", | ||||||
|  |         ".75": "rgba(230, 126, 34,  .9)", | ||||||
|  |         "1.0": "rgba(211, 84,  0,   .9)", | ||||||
|  |       }, | ||||||
|  |       shadowBlur: 10, | ||||||
|  |       shadowColor: "rgba(0,   0,   0,   .6)", | ||||||
|  |       className: null, | ||||||
|  |     }, | ||||||
|  |     repaint = function () { | ||||||
|  |       canvas.width = window.innerWidth; | ||||||
|  |       canvas.height = options.barThickness * 5; // need space for shadow | ||||||
|  |  | ||||||
|  |       var ctx = canvas.getContext("2d"); | ||||||
|  |       ctx.shadowBlur = options.shadowBlur; | ||||||
|  |       ctx.shadowColor = options.shadowColor; | ||||||
|  |  | ||||||
|  |       var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0); | ||||||
|  |       for (var stop in options.barColors) | ||||||
|  |         lineGradient.addColorStop(stop, options.barColors[stop]); | ||||||
|  |       ctx.lineWidth = options.barThickness; | ||||||
|  |       ctx.beginPath(); | ||||||
|  |       ctx.moveTo(0, options.barThickness / 2); | ||||||
|  |       ctx.lineTo( | ||||||
|  |         Math.ceil(currentProgress * canvas.width), | ||||||
|  |         options.barThickness / 2 | ||||||
|  |       ); | ||||||
|  |       ctx.strokeStyle = lineGradient; | ||||||
|  |       ctx.stroke(); | ||||||
|  |     }, | ||||||
|  |     createCanvas = function () { | ||||||
|  |       canvas = document.createElement("canvas"); | ||||||
|  |       var style = canvas.style; | ||||||
|  |       style.position = "fixed"; | ||||||
|  |       style.top = style.left = style.right = style.margin = style.padding = 0; | ||||||
|  |       style.zIndex = 100001; | ||||||
|  |       style.display = "none"; | ||||||
|  |       if (options.className) canvas.classList.add(options.className); | ||||||
|  |       document.body.appendChild(canvas); | ||||||
|  |       addEvent(window, "resize", repaint); | ||||||
|  |     }, | ||||||
|  |     topbar = { | ||||||
|  |       config: function (opts) { | ||||||
|  |         for (var key in opts) | ||||||
|  |           if (options.hasOwnProperty(key)) options[key] = opts[key]; | ||||||
|  |       }, | ||||||
|  |       show: function () { | ||||||
|  |         if (showing) return; | ||||||
|  |         showing = true; | ||||||
|  |         if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId); | ||||||
|  |         if (!canvas) createCanvas(); | ||||||
|  |         canvas.style.opacity = 1; | ||||||
|  |         canvas.style.display = "block"; | ||||||
|  |         topbar.progress(0); | ||||||
|  |         if (options.autoRun) { | ||||||
|  |           (function loop() { | ||||||
|  |             progressTimerId = window.requestAnimationFrame(loop); | ||||||
|  |             topbar.progress( | ||||||
|  |               "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2) | ||||||
|  |             ); | ||||||
|  |           })(); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       progress: function (to) { | ||||||
|  |         if (typeof to === "undefined") return currentProgress; | ||||||
|  |         if (typeof to === "string") { | ||||||
|  |           to = | ||||||
|  |             (to.indexOf("+") >= 0 || to.indexOf("-") >= 0 | ||||||
|  |               ? currentProgress | ||||||
|  |               : 0) + parseFloat(to); | ||||||
|  |         } | ||||||
|  |         currentProgress = to > 1 ? 1 : to; | ||||||
|  |         repaint(); | ||||||
|  |         return currentProgress; | ||||||
|  |       }, | ||||||
|  |       hide: function () { | ||||||
|  |         if (!showing) return; | ||||||
|  |         showing = false; | ||||||
|  |         if (progressTimerId != null) { | ||||||
|  |           window.cancelAnimationFrame(progressTimerId); | ||||||
|  |           progressTimerId = null; | ||||||
|  |         } | ||||||
|  |         (function loop() { | ||||||
|  |           if (topbar.progress("+.1") >= 1) { | ||||||
|  |             canvas.style.opacity -= 0.05; | ||||||
|  |             if (canvas.style.opacity <= 0.05) { | ||||||
|  |               canvas.style.display = "none"; | ||||||
|  |               fadeTimerId = null; | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           fadeTimerId = window.requestAnimationFrame(loop); | ||||||
|  |         })(); | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |   if (typeof module === "object" && typeof module.exports === "object") { | ||||||
|  |     module.exports = topbar; | ||||||
|  |   } else if (typeof define === "function" && define.amd) { | ||||||
|  |     define(function () { | ||||||
|  |       return topbar; | ||||||
|  |     }); | ||||||
|  |   } else { | ||||||
|  |     this.topbar = topbar; | ||||||
|  |   } | ||||||
|  | }.call(this, window, document)); | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| # This file is responsible for configuring your application | # This file is responsible for configuring your application | ||||||
| # and its dependencies with the aid of the Mix.Config module. | # and its dependencies with the aid of the Config module. | ||||||
| # | # | ||||||
| # This configuration file is loaded before any dependency and | # This configuration file is loaded before any dependency and | ||||||
| # is restricted to this project. | # is restricted to this project. | ||||||
| @@ -8,7 +8,8 @@ | |||||||
| import Config | import Config | ||||||
|  |  | ||||||
| config :cannery, | config :cannery, | ||||||
|   ecto_repos: [Cannery.Repo] |   ecto_repos: [Cannery.Repo], | ||||||
|  |   generators: [binary_id: true] | ||||||
|  |  | ||||||
| # Configures the endpoint | # Configures the endpoint | ||||||
| config :cannery, CanneryWeb.Endpoint, | config :cannery, CanneryWeb.Endpoint, | ||||||
| @@ -25,6 +26,28 @@ config :cannery, :generators, | |||||||
|   binary_id: true, |   binary_id: true, | ||||||
|   sample_binary_id: "11111111-1111-1111-1111-111111111111" |   sample_binary_id: "11111111-1111-1111-1111-111111111111" | ||||||
|  |  | ||||||
|  | # Configures the mailer | ||||||
|  | # | ||||||
|  | # By default it uses the "Local" adapter which stores the emails | ||||||
|  | # locally. You can see the emails in your browser, at "/dev/mailbox". | ||||||
|  | # | ||||||
|  | # For production it's recommended to configure a different adapter | ||||||
|  | # at the `config/runtime.exs`. | ||||||
|  | config :cannery, Cannery.Mailer, adapter: Swoosh.Adapters.Local | ||||||
|  |  | ||||||
|  | # Swoosh API client is needed for adapters other than SMTP. | ||||||
|  | config :swoosh, :api_client, false | ||||||
|  |  | ||||||
|  | # Configure esbuild (the version is required) | ||||||
|  | # config :esbuild, | ||||||
|  | #   version: "0.14.0", | ||||||
|  | #   default: [ | ||||||
|  | #     args: | ||||||
|  | #       ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), | ||||||
|  | #     cd: Path.expand("../assets", __DIR__), | ||||||
|  | #     env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} | ||||||
|  | #   ] | ||||||
|  |  | ||||||
| # Configures Elixir's Logger | # Configures Elixir's Logger | ||||||
| config :logger, :console, | config :logger, :console, | ||||||
|   format: "$time $metadata[$level] $message\n", |   format: "$time $metadata[$level] $message\n", | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ config :cannery, Cannery.Repo, | |||||||
|   url: |   url: | ||||||
|     System.get_env("DATABASE_URL") || |     System.get_env("DATABASE_URL") || | ||||||
|       "ecto://postgres:postgres@localhost/cannery_dev", |       "ecto://postgres:postgres@localhost/cannery_dev", | ||||||
|  |   show_sensitive_data_on_connection_error: true, | ||||||
|   pool_size: 10 |   pool_size: 10 | ||||||
|  |  | ||||||
| # For development, we disable any cache and enable | # For development, we disable any cache and enable | ||||||
| @@ -12,12 +13,18 @@ config :cannery, Cannery.Repo, | |||||||
| # | # | ||||||
| # The watchers configuration can be used to run external | # The watchers configuration can be used to run external | ||||||
| # watchers to your application. For example, we use it | # watchers to your application. For example, we use it | ||||||
| # with webpack to recompile .js and .css sources. | # with esbuild to bundle .js and .css sources. | ||||||
| config :cannery, CanneryWeb.Endpoint, | config :cannery, CanneryWeb.Endpoint, | ||||||
|   debug_errors: true, |   # Binding to loopback ipv4 address prevents access from other machines. | ||||||
|   code_reloader: true, |   # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. | ||||||
|  |   http: [ip: {0, 0, 0, 0}, port: 4000], | ||||||
|   check_origin: false, |   check_origin: false, | ||||||
|  |   code_reloader: true, | ||||||
|  |   debug_errors: true, | ||||||
|  |   secret_key_base: "dg2lccMgaY3+ZeKppR+ondk4ZRaANZGIN0LMZT1u1uzscH4jO5W9a9b9V9BkC+MW", | ||||||
|   watchers: [ |   watchers: [ | ||||||
|  |     # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args) | ||||||
|  |     # esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]} | ||||||
|     node: [ |     node: [ | ||||||
|       "node_modules/webpack/bin/webpack.js", |       "node_modules/webpack/bin/webpack.js", | ||||||
|       "--mode", |       "--mode", | ||||||
| @@ -58,8 +65,8 @@ config :cannery, CanneryWeb.Endpoint, | |||||||
|     patterns: [ |     patterns: [ | ||||||
|       ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", |       ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", | ||||||
|       ~r"priv/gettext/.*(po)$", |       ~r"priv/gettext/.*(po)$", | ||||||
|       ~r"lib/cannery_web/.*(live|views)/.*(ex|leex)$", |       ~r"lib/cannery_web/(live|views)/.*(ex)$", | ||||||
|       ~r"lib/cannery_web/templates/.*(eex|leex)$" |       ~r"lib/cannery_web/templates/.*(eex)$" | ||||||
|     ] |     ] | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,14 +25,14 @@ config :logger, level: :info | |||||||
| # to the previous section and set your `:url` port to 443: | # to the previous section and set your `:url` port to 443: | ||||||
| # | # | ||||||
| #     config :cannery, CanneryWeb.Endpoint, | #     config :cannery, CanneryWeb.Endpoint, | ||||||
| #       ... | #       ..., | ||||||
| #       url: [host: "localhost", port: 443], | #       url: [host: "example.com", port: 443], | ||||||
| #       https: [ | #       https: [ | ||||||
|  | #         ..., | ||||||
| #         port: 443, | #         port: 443, | ||||||
| #         cipher_suite: :strong, | #         cipher_suite: :strong, | ||||||
| #         keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), | #         keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), | ||||||
| #         certfile: System.get_env("SOME_APP_SSL_CERT_PATH"), | #         certfile: System.get_env("SOME_APP_SSL_CERT_PATH") | ||||||
| #         transport_options: [socket_opts: [:inet6]] |  | ||||||
| #       ] | #       ] | ||||||
| # | # | ||||||
| # The `cipher_suite` is set to `:strong` to support only the | # The `cipher_suite` is set to `:strong` to support only the | ||||||
|   | |||||||
| @@ -1,33 +0,0 @@ | |||||||
| # In this file, we load production configuration and secrets |  | ||||||
| # from environment variables. You can also hardcode secrets, |  | ||||||
| # although such is generally not recommended and you have to |  | ||||||
| # remember to add this file to your .gitignore. |  | ||||||
| import Config |  | ||||||
|  |  | ||||||
| database_url = |  | ||||||
|   System.get_env("DATABASE_URL") || |  | ||||||
|     "ecto://postgres:postgres@cannery-db/cannery" |  | ||||||
|  |  | ||||||
| config :cannery, Cannery.Repo, |  | ||||||
|   # ssl: true, |  | ||||||
|   url: database_url, |  | ||||||
|   pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10") |  | ||||||
|  |  | ||||||
| secret_key_base = |  | ||||||
|   System.get_env("SECRET_KEY_BASE") || |  | ||||||
|     raise """ |  | ||||||
|     environment variable SECRET_KEY_BASE is missing. |  | ||||||
|     You can generate one by calling: mix phx.gen.secret |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
| host = System.get_env("HOST") || "localhost" |  | ||||||
|  |  | ||||||
| config :cannery, CanneryWeb.Endpoint, |  | ||||||
|   url: [scheme: "https", host: host, port: "443"], |  | ||||||
|   http: [ |  | ||||||
|     port: String.to_integer(System.get_env("PORT") || "4000"), |  | ||||||
|     transport_options: [socket_opts: [:inet6]] |  | ||||||
|   ], |  | ||||||
|   secret_key_base: secret_key_base, |  | ||||||
|   server: true, |  | ||||||
|   registration: System.get_env("REGISTRATION") || "invite" |  | ||||||
							
								
								
									
										83
									
								
								config/runtime.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								config/runtime.exs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | import Config | ||||||
|  |  | ||||||
|  | # config/runtime.exs is executed for all environments, including | ||||||
|  | # during releases. It is executed after compilation and before the | ||||||
|  | # system starts, so it is typically used to load production configuration | ||||||
|  | # and secrets from environment variables or elsewhere. Do not define | ||||||
|  | # any compile-time configuration in here, as it won't be applied. | ||||||
|  | # The block below contains prod specific runtime configuration. | ||||||
|  |  | ||||||
|  | # Start the phoenix server if environment is set and running in a release | ||||||
|  | if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do | ||||||
|  |   config :cannery, CanneryWeb.Endpoint, server: true | ||||||
|  | end | ||||||
|  |  | ||||||
|  | if config_env() == :prod do | ||||||
|  |   database_url = | ||||||
|  |     System.get_env("DATABASE_URL") || | ||||||
|  |       "ecto://postgres:postgres@cannery-db/cannery" | ||||||
|  |  | ||||||
|  |   maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: [] | ||||||
|  |  | ||||||
|  |   config :cannery, Cannery.Repo, | ||||||
|  |     # ssl: true, | ||||||
|  |     url: database_url, | ||||||
|  |     pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), | ||||||
|  |     socket_options: maybe_ipv6 | ||||||
|  |  | ||||||
|  |   # The secret key base is used to sign/encrypt cookies and other secrets. | ||||||
|  |   # A default value is used in config/dev.exs and config/test.exs but you | ||||||
|  |   # want to use a different value for prod and you most likely don't want | ||||||
|  |   # to check this value into version control, so we use an environment | ||||||
|  |   # variable instead. | ||||||
|  |   secret_key_base = | ||||||
|  |     System.get_env("SECRET_KEY_BASE") || | ||||||
|  |       raise """ | ||||||
|  |       environment variable SECRET_KEY_BASE is missing. | ||||||
|  |       You can generate one by calling: mix phx.gen.secret | ||||||
|  |       """ | ||||||
|  |  | ||||||
|  |   host = System.get_env("HOST") || "localhost" | ||||||
|  |  | ||||||
|  |   config :cannery, CanneryWeb.Endpoint, | ||||||
|  |     url: [scheme: "https", host: host, port: 443], | ||||||
|  |     http: [ | ||||||
|  |       # Enable IPv6 and bind on all interfaces. | ||||||
|  |       # Set it to  {0, 0, 0, 0, 0, 0, 0, 1} for local network only access. | ||||||
|  |       # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html | ||||||
|  |       # for details about using IPv6 vs IPv4 and loopback vs public addresses. | ||||||
|  |       ip: {0, 0, 0, 0, 0, 0, 0, 0}, | ||||||
|  |       port: String.to_integer(System.get_env("PORT") || "4000") | ||||||
|  |     ], | ||||||
|  |     secret_key_base: secret_key_base, | ||||||
|  |     server: true, | ||||||
|  |     registration: System.get_env("REGISTRATION") || "invite" | ||||||
|  |  | ||||||
|  |   # ## Using releases | ||||||
|  |   # | ||||||
|  |   # If you are doing OTP releases, you need to instruct Phoenix | ||||||
|  |   # to start each relevant endpoint: | ||||||
|  |   # | ||||||
|  |   #     config :cannery, CanneryWeb.Endpoint, server: true | ||||||
|  |   # | ||||||
|  |   # Then you can assemble a release by calling `mix release`. | ||||||
|  |   # See `mix help release` for more information. | ||||||
|  |  | ||||||
|  |   # ## Configuring the mailer | ||||||
|  |   # | ||||||
|  |   # In production you need to configure the mailer to use a different adapter. | ||||||
|  |   # Also, you may need to configure the Swoosh API client of your choice if you | ||||||
|  |   # are not using SMTP. Here is an example of the configuration: | ||||||
|  |   # | ||||||
|  |   #     config :cannery, Cannery.Mailer, | ||||||
|  |   #       adapter: Swoosh.Adapters.Mailgun, | ||||||
|  |   #       api_key: System.get_env("MAILGUN_API_KEY"), | ||||||
|  |   #       domain: System.get_env("MAILGUN_DOMAIN") | ||||||
|  |   # | ||||||
|  |   # For this example you need include a HTTP client required by Swoosh API client. | ||||||
|  |   # Swoosh supports Hackney and Finch out of the box: | ||||||
|  |   # | ||||||
|  |   #     config :swoosh, :api_client, Swoosh.ApiClient.Hackney | ||||||
|  |   # | ||||||
|  |   # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details. | ||||||
|  | end | ||||||
| @@ -11,15 +11,23 @@ config :bcrypt_elixir, :log_rounds, 1 | |||||||
| config :cannery, Cannery.Repo, | config :cannery, Cannery.Repo, | ||||||
|   username: "postgres", |   username: "postgres", | ||||||
|   password: "postgres", |   password: "postgres", | ||||||
|   database: "cannery_test#{System.get_env("MIX_TEST_PARTITION")}", |  | ||||||
|   hostname: "localhost", |   hostname: "localhost", | ||||||
|   pool: Ecto.Adapters.SQL.Sandbox |   database: "cannery_test#{System.get_env("MIX_TEST_PARTITION")}", | ||||||
|  |   pool: Ecto.Adapters.SQL.Sandbox, | ||||||
|  |   pool_size: 10 | ||||||
|  |  | ||||||
| # We don't run a server during test. If one is required, | # We don't run a server during test. If one is required, | ||||||
| # you can enable the server option below. | # you can enable the server option below. | ||||||
| config :cannery, CanneryWeb.Endpoint, | config :cannery, CanneryWeb.Endpoint, | ||||||
|   http: [port: 4002], |   http: [ip: {127, 0, 0, 1}, port: 4002], | ||||||
|  |   secret_key_base: "S3qq9QtUdsFtlYej+HTjAVN95uP5i5tf2sPYINWSQfCKJghFj2B1+wTAoljZyHOK", | ||||||
|   server: false |   server: false | ||||||
|  |  | ||||||
|  | # In test we don't send emails. | ||||||
|  | config :cannery, Cannery.Mailer, adapter: Swoosh.Adapters.Test | ||||||
|  |  | ||||||
| # Print only warnings and errors during test | # Print only warnings and errors during test | ||||||
| config :logger, level: :warn | config :logger, level: :warn | ||||||
|  |  | ||||||
|  | # Initialize plugs at runtime for faster test compilation | ||||||
|  | config :phoenix, :plug_init_mode, :runtime | ||||||
|   | |||||||
| @@ -5,19 +5,21 @@ defmodule Cannery.Application do | |||||||
|  |  | ||||||
|   use Application |   use Application | ||||||
|  |  | ||||||
|  |   @impl true | ||||||
|   def start(_type, _args) do |   def start(_type, _args) do | ||||||
|     children = [ |     children = [ | ||||||
|       # Start the Ecto repository |       # Start the Ecto repository | ||||||
|       Cannery.Repo, |       Cannery.Repo, | ||||||
|       Cannery.Repo.Migrator, |  | ||||||
|       # Start the Telemetry supervisor |       # Start the Telemetry supervisor | ||||||
|       CanneryWeb.Telemetry, |       CanneryWeb.Telemetry, | ||||||
|       # Start the PubSub system |       # Start the PubSub system | ||||||
|       {Phoenix.PubSub, name: Cannery.PubSub}, |       {Phoenix.PubSub, name: Cannery.PubSub}, | ||||||
|       # Start the Endpoint (http/https) |       # Start the Endpoint (http/https) | ||||||
|       CanneryWeb.Endpoint |       CanneryWeb.Endpoint, | ||||||
|       # Start a worker by calling: Cannery.Worker.start_link(arg) |       # Start a worker by calling: Cannery.Worker.start_link(arg) | ||||||
|       # {Cannery.Worker, arg} |       # {Cannery.Worker, arg}, | ||||||
|  |       # Automatically migrate on start | ||||||
|  |       Cannery.Repo.Migrator | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     # See https://hexdocs.pm/elixir/Supervisor.html |     # See https://hexdocs.pm/elixir/Supervisor.html | ||||||
| @@ -28,6 +30,7 @@ defmodule Cannery.Application do | |||||||
|  |  | ||||||
|   # Tell Phoenix to update the endpoint configuration |   # Tell Phoenix to update the endpoint configuration | ||||||
|   # whenever the application is updated. |   # whenever the application is updated. | ||||||
|  |   @impl true | ||||||
|   def config_change(changed, _new, removed) do |   def config_change(changed, _new, removed) do | ||||||
|     CanneryWeb.Endpoint.config_change(changed, removed) |     CanneryWeb.Endpoint.config_change(changed, removed) | ||||||
|     :ok |     :ok | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								lib/cannery/mailer.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								lib/cannery/mailer.ex
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | defmodule Cannery.Mailer do | ||||||
|  |   use Swoosh.Mailer, otp_app: :cannery | ||||||
|  | end | ||||||
| @@ -59,6 +59,14 @@ defmodule CanneryWeb do | |||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def component do | ||||||
|  |     quote do | ||||||
|  |       use Phoenix.Component | ||||||
|  |  | ||||||
|  |       unquote(view_helpers()) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|   def router do |   def router do | ||||||
|     quote do |     quote do | ||||||
|       use Phoenix.Router |       use Phoenix.Router | ||||||
| @@ -81,7 +89,7 @@ defmodule CanneryWeb do | |||||||
|       # Use all HTML functionality (forms, tags, etc) |       # Use all HTML functionality (forms, tags, etc) | ||||||
|       use Phoenix.HTML |       use Phoenix.HTML | ||||||
|  |  | ||||||
|       # Import LiveView helpers (live_render, live_component, live_patch, etc) |       # Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc) | ||||||
|       import Phoenix.LiveView.Helpers |       import Phoenix.LiveView.Helpers | ||||||
|       import CanneryWeb.LiveHelpers |       import CanneryWeb.LiveHelpers | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,35 +0,0 @@ | |||||||
| defmodule CanneryWeb.UserSocket do |  | ||||||
|   use Phoenix.Socket |  | ||||||
|  |  | ||||||
|   ## Channels |  | ||||||
|   # channel "room:*", CanneryWeb.RoomChannel |  | ||||||
|  |  | ||||||
|   # Socket params are passed from the client and can |  | ||||||
|   # be used to verify and authenticate a user. After |  | ||||||
|   # verification, you can put default assigns into |  | ||||||
|   # the socket that will be set for all channels, ie |  | ||||||
|   # |  | ||||||
|   #     {:ok, socket |> assign(:user_id, verified_user_id)} |  | ||||||
|   # |  | ||||||
|   # To deny connection, return `:error`. |  | ||||||
|   # |  | ||||||
|   # See `Phoenix.Token` documentation for examples in |  | ||||||
|   # performing token verification on connect. |  | ||||||
|   @impl true |  | ||||||
|   def connect(_params, socket, _connect_info) do |  | ||||||
|     {:ok, socket} |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   # Socket id's are topics that allow you to identify all sockets for a given user: |  | ||||||
|   # |  | ||||||
|   #     def id(socket), do: "user_socket:#{socket.assigns.user_id}" |  | ||||||
|   # |  | ||||||
|   # Would allow you to broadcast a "disconnect" event and terminate |  | ||||||
|   # all active sockets and channels for a given user: |  | ||||||
|   # |  | ||||||
|   #     CanneryWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) |  | ||||||
|   # |  | ||||||
|   # Returning `nil` makes this socket anonymous. |  | ||||||
|   @impl true |  | ||||||
|   def id(_socket), do: nil |  | ||||||
| end |  | ||||||
| @@ -3,6 +3,7 @@ defmodule CanneryWeb.UserAuth do | |||||||
|   import Phoenix.Controller |   import Phoenix.Controller | ||||||
|  |  | ||||||
|   alias Cannery.Accounts |   alias Cannery.Accounts | ||||||
|  |   alias CanneryWeb.{HomeLive} | ||||||
|   alias CanneryWeb.Router.Helpers, as: Routes |   alias CanneryWeb.Router.Helpers, as: Routes | ||||||
|  |  | ||||||
|   # Make the remember me cookie valid for 60 days. |   # Make the remember me cookie valid for 60 days. | ||||||
| @@ -149,7 +150,7 @@ defmodule CanneryWeb.UserAuth do | |||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "You are not authorized to view this page.") |       |> put_flash(:error, "You are not authorized to view this page.") | ||||||
|       |> maybe_store_return_to() |       |> maybe_store_return_to() | ||||||
|       |> redirect(to: Routes.home_path(conn, :index)) |       |> redirect(to: Routes.live_path(conn, HomeLive)) | ||||||
|       |> halt() |       |> halt() | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ defmodule CanneryWeb.UserRegistrationController do | |||||||
|  |  | ||||||
|   alias Cannery.{Accounts, Invites} |   alias Cannery.{Accounts, Invites} | ||||||
|   alias Cannery.Accounts.User |   alias Cannery.Accounts.User | ||||||
|   alias CanneryWeb.UserAuth |   alias CanneryWeb.{HomeLive, UserAuth} | ||||||
|  |  | ||||||
|   def new(conn, %{"invite" => invite_token}) do |   def new(conn, %{"invite" => invite_token}) do | ||||||
|     invite = Invites.get_invite_by_token(invite_token) |     invite = Invites.get_invite_by_token(invite_token) | ||||||
| @@ -13,7 +13,7 @@ defmodule CanneryWeb.UserRegistrationController do | |||||||
|     else |     else | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Sorry, this invite was not found or expired") |       |> put_flash(:error, "Sorry, this invite was not found or expired") | ||||||
|       |> redirect(to: Routes.home_path(CanneryWeb.Endpoint, :index)) |       |> redirect(to: Routes.live_path(CanneryWeb.Endpoint, HomeLive)) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -23,7 +23,7 @@ defmodule CanneryWeb.UserRegistrationController do | |||||||
|     else |     else | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Sorry, public registration is disabled") |       |> put_flash(:error, "Sorry, public registration is disabled") | ||||||
|       |> redirect(to: Routes.home_path(CanneryWeb.Endpoint, :index)) |       |> redirect(to: Routes.live_path(CanneryWeb.Endpoint, HomeLive)) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -41,7 +41,7 @@ defmodule CanneryWeb.UserRegistrationController do | |||||||
|     else |     else | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Sorry, this invite was not found or expired") |       |> put_flash(:error, "Sorry, this invite was not found or expired") | ||||||
|       |> redirect(to: Routes.home_path(CanneryWeb.Endpoint, :index)) |       |> redirect(to: Routes.live_path(CanneryWeb.Endpoint, HomeLive)) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -51,7 +51,7 @@ defmodule CanneryWeb.UserRegistrationController do | |||||||
|     else |     else | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Sorry, public registration is disabled") |       |> put_flash(:error, "Sorry, public registration is disabled") | ||||||
|       |> redirect(to: Routes.home_path(CanneryWeb.Endpoint, :index)) |       |> redirect(to: Routes.live_path(CanneryWeb.Endpoint, HomeLive)) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ defmodule CanneryWeb.UserSettingsController do | |||||||
|   use CanneryWeb, :controller |   use CanneryWeb, :controller | ||||||
|  |  | ||||||
|   alias Cannery.Accounts |   alias Cannery.Accounts | ||||||
|   alias CanneryWeb.UserAuth |   alias CanneryWeb.{HomeLive, UserAuth} | ||||||
|  |  | ||||||
|   plug :assign_email_and_password_changesets |   plug :assign_email_and_password_changesets | ||||||
|  |  | ||||||
| @@ -70,7 +70,7 @@ defmodule CanneryWeb.UserSettingsController do | |||||||
|  |  | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Your account has been deleted") |       |> put_flash(:error, "Your account has been deleted") | ||||||
|       |> redirect(to: Routes.home_path(conn, :index)) |       |> redirect(to: Routes.live_path(conn, HomeLive)) | ||||||
|     else |     else | ||||||
|       conn |       conn | ||||||
|       |> put_flash(:error, "Unable to delete user") |       |> put_flash(:error, "Unable to delete user") | ||||||
|   | |||||||
| @@ -7,13 +7,9 @@ defmodule CanneryWeb.Endpoint do | |||||||
|   @session_options [ |   @session_options [ | ||||||
|     store: :cookie, |     store: :cookie, | ||||||
|     key: "_cannery_key", |     key: "_cannery_key", | ||||||
|     signing_salt: "fxAnJltS" |     signing_salt: "N8eMKwCG" | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
|   socket "/socket", CanneryWeb.UserSocket, |  | ||||||
|     websocket: true, |  | ||||||
|     longpoll: false |  | ||||||
|  |  | ||||||
|   socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]] |   socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]] | ||||||
|  |  | ||||||
|   # Serve at "/" the static files from "priv/static" directory. |   # Serve at "/" the static files from "priv/static" directory. | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
|     <li class="flex flex-row justify-center space-x-2"> |     <li class="flex flex-row justify-center space-x-2"> | ||||||
|       <b>Easy to Use:</b> |       <b>Easy to Use:</b> | ||||||
|       <p> |       <p> | ||||||
|         Cannery lets you easily keep an eye on your ammo levels after range day |         Cannery lets you easily keep an eye on your ammo levels before and after range day | ||||||
|       </p> |       </p> | ||||||
|     </li> |     </li> | ||||||
|     <li class="flex flex-row justify-center space-x-2"> |     <li class="flex flex-row justify-center space-x-2"> | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ defmodule CanneryWeb.ModalComponent do | |||||||
|  |  | ||||||
|         <%# modal content %> |         <%# modal content %> | ||||||
|         <div class="w-full flex flex-col space-y-4 justify-center items-center"> |         <div class="w-full flex flex-col space-y-4 justify-center items-center"> | ||||||
|           <%= live_component @socket, @component, @opts %> |           <%= live_component @component, @opts %> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ defmodule CanneryWeb.Router do | |||||||
|   scope "/", CanneryWeb do |   scope "/", CanneryWeb do | ||||||
|     pipe_through :browser |     pipe_through :browser | ||||||
|  |  | ||||||
|     live "/", HomeLive, :index |     live "/", HomeLive | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   ## Authentication routes |   ## Authentication routes | ||||||
| @@ -94,4 +94,16 @@ defmodule CanneryWeb.Router do | |||||||
|     post "/users/confirm", UserConfirmationController, :create |     post "/users/confirm", UserConfirmationController, :create | ||||||
|     get "/users/confirm/:token", UserConfirmationController, :confirm |     get "/users/confirm/:token", UserConfirmationController, :confirm | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   # Enables the Swoosh mailbox preview in development. | ||||||
|  |   # | ||||||
|  |   # Note that preview only shows emails that were sent by the same | ||||||
|  |   # node running the Phoenix server. | ||||||
|  |   if Mix.env() == :dev do | ||||||
|  |     scope "/dev" do | ||||||
|  |       pipe_through :browser | ||||||
|  |  | ||||||
|  |       forward "/mailbox", Plug.Swoosh.MailboxPreview | ||||||
|  |     end | ||||||
|  |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -31,11 +31,27 @@ defmodule CanneryWeb.Telemetry do | |||||||
|       ), |       ), | ||||||
|  |  | ||||||
|       # Database Metrics |       # Database Metrics | ||||||
|       summary("cannery.repo.query.total_time", unit: {:native, :millisecond}), |       summary("cannery.repo.query.total_time", | ||||||
|       summary("cannery.repo.query.decode_time", unit: {:native, :millisecond}), |         unit: {:native, :millisecond}, | ||||||
|       summary("cannery.repo.query.query_time", unit: {:native, :millisecond}), |         description: "The sum of the other measurements" | ||||||
|       summary("cannery.repo.query.queue_time", unit: {:native, :millisecond}), |       ), | ||||||
|       summary("cannery.repo.query.idle_time", unit: {:native, :millisecond}), |       summary("cannery.repo.query.decode_time", | ||||||
|  |         unit: {:native, :millisecond}, | ||||||
|  |         description: "The time spent decoding the data received from the database" | ||||||
|  |       ), | ||||||
|  |       summary("cannery.repo.query.query_time", | ||||||
|  |         unit: {:native, :millisecond}, | ||||||
|  |         description: "The time spent executing the query" | ||||||
|  |       ), | ||||||
|  |       summary("cannery.repo.query.queue_time", | ||||||
|  |         unit: {:native, :millisecond}, | ||||||
|  |         description: "The time spent waiting for a database connection" | ||||||
|  |       ), | ||||||
|  |       summary("cannery.repo.query.idle_time", | ||||||
|  |         unit: {:native, :millisecond}, | ||||||
|  |         description: | ||||||
|  |           "The time the connection spent waiting before being checked out for the query" | ||||||
|  |       ), | ||||||
|  |  | ||||||
|       # VM Metrics |       # VM Metrics | ||||||
|       summary("vm.memory.total", unit: {:byte, :kilobyte}), |       summary("vm.memory.total", unit: {:byte, :kilobyte}), | ||||||
|   | |||||||
| @@ -1,16 +1,21 @@ | |||||||
| <main role="main" class="container min-w-full min-h-full"> | 
 | ||||||
|  | <main class="container min-w-full min-h-full"> | ||||||
|   <header> |   <header> | ||||||
|     <%= live_component CanneryWeb.Live.Component.Topbar, current_user: assigns[:current_user] %> |     <%= live_component CanneryWeb.Live.Component.Topbar, current_user: assigns[:current_user] %> | ||||||
| 
 | 
 | ||||||
|     <div class="mx-8 my-2 flex flex-col space-y-4 text-center"> |     <div class="mx-8 my-2 flex flex-col space-y-4 text-center"> | ||||||
|       <%= if live_flash(@flash, :info) do %> |       <%= if live_flash(@flash, :info) do %> | ||||||
|         <p class="alert alert-info" role="alert"> |         <p class="alert alert-info" role="alert" | ||||||
|  |           phx-click="lv:clear-flash" | ||||||
|  |           phx-value-key="info"> | ||||||
|           <%= live_flash(@flash, :info) %> |           <%= live_flash(@flash, :info) %> | ||||||
|         </p> |         </p> | ||||||
|       <% end %> |       <% end %> | ||||||
| 
 | 
 | ||||||
|       <%= if live_flash(@flash, :error) do %> |       <%= if live_flash(@flash, :error) do %> | ||||||
|         <p class="alert alert-danger" role="alert"> |         <p class="alert alert-danger" role="alert" | ||||||
|  |           phx-click="lv:clear-flash" | ||||||
|  |           phx-value-key="error"> | ||||||
|           <%= live_flash(@flash, :error) %> |           <%= live_flash(@flash, :error) %> | ||||||
|         </p> |         </p> | ||||||
|       <% end %> |       <% end %> | ||||||
| @@ -6,8 +6,8 @@ | |||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||||||
|     <%= csrf_meta_tag() %> |     <%= csrf_meta_tag() %> | ||||||
|     <%= live_title_tag assigns[:page_title] || "Cannery", suffix: "" %> |     <%= live_title_tag assigns[:page_title] || "Cannery", suffix: "" %> | ||||||
|     <link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/> |     <link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")}/> | ||||||
|     <script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script> |     <script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/js/app.js")}></script> | ||||||
|   </head> |   </head> | ||||||
|   <body class="m-0 p-0 min-w-full min-h-full"> |   <body class="m-0 p-0 min-w-full min-h-full"> | ||||||
|     <%= @inner_content %> |     <%= @inner_content %> | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| <nav role="navigation"> | <nav role="navigation"> | ||||||
|   <div class="flex flex-row justify-between items-center space-x-4"> |   <div class="flex flex-row justify-between items-center space-x-4"> | ||||||
|     <%= link to: Routes.home_path(CanneryWeb.Endpoint, :index) do %> |     <%= link to: Routes.live_path(CanneryWeb.Endpoint, HomeLive) do %> | ||||||
|       <h1 class="leading-5 text-xl text-white hover:underline">Cannery</h1> |       <h1 class="leading-5 text-xl text-white hover:underline">Cannery</h1> | ||||||
|     <% end %> |     <% end %> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,11 @@ | |||||||
| defmodule CanneryWeb.LayoutView do | defmodule CanneryWeb.LayoutView do | ||||||
|   use CanneryWeb, :view |   use CanneryWeb, :view | ||||||
|   alias Cannery.{Accounts} |   alias Cannery.{Accounts} | ||||||
|  |   alias CanneryWeb.{HomeLive} | ||||||
|  |  | ||||||
|  |   # Phoenix LiveDashboard is available only in development by default, | ||||||
|  |   # so we instruct Elixir to not warn if the dashboard route is missing. | ||||||
|  |   @compile {:no_warn_undefined, {Routes, :live_dashboard_path, 2}} | ||||||
|  |  | ||||||
|   def get_title(conn) do |   def get_title(conn) do | ||||||
|     if conn.assigns |> Map.has_key?(:title) do |     if conn.assigns |> Map.has_key?(:title) do | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								mix.exs
									
									
									
									
									
								
							| @@ -5,9 +5,9 @@ defmodule Cannery.MixProject do | |||||||
|     [ |     [ | ||||||
|       app: :cannery, |       app: :cannery, | ||||||
|       version: "0.1.0", |       version: "0.1.0", | ||||||
|       elixir: "~> 1.7", |       elixir: "~> 1.12", | ||||||
|       elixirc_paths: elixirc_paths(Mix.env()), |       elixirc_paths: elixirc_paths(Mix.env()), | ||||||
|       compilers: [:phoenix, :gettext] ++ Mix.compilers(), |       compilers: [:gettext] ++ Mix.compilers(), | ||||||
|       start_permanent: Mix.env() == :prod, |       start_permanent: Mix.env() == :prod, | ||||||
|       aliases: aliases(), |       aliases: aliases(), | ||||||
|       deps: deps(), |       deps: deps(), | ||||||
| @@ -35,21 +35,22 @@ defmodule Cannery.MixProject do | |||||||
|   defp deps do |   defp deps do | ||||||
|     [ |     [ | ||||||
|       {:bcrypt_elixir, "~> 2.0"}, |       {:bcrypt_elixir, "~> 2.0"}, | ||||||
|       {:phoenix, "~> 1.5.10"}, |       {:phoenix, "~> 1.6.6"}, | ||||||
|       {:phoenix_ecto, "~> 4.1"}, |       {:phoenix_ecto, "~> 4.4"}, | ||||||
|       {:ecto_sql, "~> 3.4"}, |       {:ecto_sql, "~> 3.6"}, | ||||||
|       {:postgrex, ">= 0.0.0"}, |       {:postgrex, ">= 0.0.0"}, | ||||||
|       {:phoenix_live_view, "~> 0.15.1"}, |       {:phoenix_html, "~> 3.0"}, | ||||||
|       {:floki, ">= 0.30.0", only: :test}, |  | ||||||
|       {:phoenix_html, "~> 2.11"}, |  | ||||||
|       {:phoenix_live_reload, "~> 1.2", only: :dev}, |       {:phoenix_live_reload, "~> 1.2", only: :dev}, | ||||||
|       {:phoenix_live_dashboard, "~> 0.4"}, |       {:phoenix_live_view, "~> 0.17.5"}, | ||||||
|       {:telemetry_metrics, "~> 0.4"}, |       {:floki, ">= 0.30.0", only: :test}, | ||||||
|       {:telemetry_poller, "~> 0.4"}, |       {:phoenix_live_dashboard, "~> 0.6"}, | ||||||
|       {:gettext, "~> 0.11"}, |       # {:esbuild, "~> 0.3", runtime: Mix.env() == :dev}, | ||||||
|       {:jason, "~> 1.0"}, |       {:swoosh, "~> 1.3"}, | ||||||
|       {:plug_cowboy, "~> 2.0"}, |       {:telemetry_metrics, "~> 0.6"}, | ||||||
|       {:phx_gen_auth, "~> 0.7", only: [:dev], runtime: false}, |       {:telemetry_poller, "~> 1.0"}, | ||||||
|  |       {:gettext, "~> 0.18"}, | ||||||
|  |       {:jason, "~> 1.2"}, | ||||||
|  |       {:plug_cowboy, "~> 2.5"}, | ||||||
|       {:ecto_psql_extras, "~> 0.6"}, |       {:ecto_psql_extras, "~> 0.6"}, | ||||||
|       {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, |       {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, | ||||||
|       {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, |       {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								mix.lock
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								mix.lock
									
									
									
									
									
								
							| @@ -1,41 +1,44 @@ | |||||||
| %{ | %{ | ||||||
|   "bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.0", "6cb662d5c1b0a8858801cf20997bd006e7016aa8c52959c9ef80e0f34fb60b7a", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2c81d61d4f6ed0e5cf7bf27a9109b791ff216a1034b3d541327484f46dd43769"}, |   "bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"}, | ||||||
|   "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, |   "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, | ||||||
|   "comeonin": {:hex, :comeonin, "5.3.2", "5c2f893d05c56ae3f5e24c1b983c2d5dfb88c6d979c9287a76a7feb1e1d8d646", [:mix], [], "hexpm", "d0993402844c49539aeadb3fe46a3c9bd190f1ecf86b6f9ebd71957534c95f04"}, |   "castore": {:hex, :castore, "0.1.14", "3f6d7c7c1574c402fef29559d3f1a7389ba3524bc6a090a5e9e6abc3af65dcca", [:mix], [], "hexpm", "b34af542eadb727e6c8b37fdf73e18b2e02eb483a4ea0b52fd500bc23f052b7b"}, | ||||||
|  |   "comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"}, | ||||||
|   "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, |   "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, | ||||||
|   "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, |   "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, | ||||||
|   "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, |   "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, | ||||||
|   "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, |   "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, | ||||||
|   "credo": {:hex, :credo, "1.5.6", "e04cc0fdc236fefbb578e0c04bd01a471081616e741d386909e527ac146016c6", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4b52a3e558bd64e30de62a648518a5ea2b6e3e5d2b164ef5296244753fc7eb17"}, |   "credo": {:hex, :credo, "1.6.2", "2f82b29a47c0bb7b72f023bf3a34d151624f1cbe1e6c4e52303b05a11166a701", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ae9dc112bc368e7b145c547bec2ed257ef88955851c15057c7835251a17211c6"}, | ||||||
|   "db_connection": {:hex, :db_connection, "2.4.0", "d04b1b73795dae60cead94189f1b8a51cc9e1f911c234cc23074017c43c031e5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad416c21ad9f61b3103d254a71b63696ecadb6a917b36f563921e0de00d7d7c8"}, |   "db_connection": {:hex, :db_connection, "2.4.1", "6411f6e23f1a8b68a82fa3a36366d4881f21f47fc79a9efb8c615e62050219da", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ea36d226ec5999781a9a8ad64e5d8c4454ecedc7a4d643e4832bf08efca01f00"}, | ||||||
|   "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, |   "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, | ||||||
|   "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, |   "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, | ||||||
|   "ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"}, |   "ecto": {:hex, :ecto, "3.7.1", "a20598862351b29f80f285b21ec5297da1181c0442687f9b8329f0445d228892", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d36e5b39fc479e654cffd4dbe1865d9716e4a9b6311faff799b6f90ab81b8638"}, | ||||||
|   "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.6.5", "161a4343d2befafef79f7a9e73a85fe2543ab1933ea211838ad76c372d4b6da2", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.15.7", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "5dbe26a78110019d2192512201a17d15d691d1a7bc72e04484fce7ed4576582b"}, |   "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.4", "5d43fd088d39a158c860b17e8d210669587f63ec89ea122a4654861c8c6e2db4", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.15.7", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "311db02f1b772e3d0dc7f56a05044b5e1499d78ed6abf38885e1ca70059449e5"}, | ||||||
|   "ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"}, |   "ecto_sql": {:hex, :ecto_sql, "3.7.1", "8de624ef50b2a8540252d8c60506379fbbc2707be1606853df371cf53df5d053", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2b42a32e2ce92f64aba5c88617891ab3b0ba34f3f3a503fa20009eae1a401c81"}, | ||||||
|   "elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"}, |   "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, | ||||||
|   "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, |   "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, | ||||||
|  |   "esbuild": {:hex, :esbuild, "0.4.0", "9f17db148aead4cf1e6e6a584214357287a93407b5fb51a031f122b61385d4c2", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "b61e4e6b92ffe45e4ee4755a22de6211a67c67987dc02afb35a425a0add1d447"}, | ||||||
|   "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, |   "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, | ||||||
|   "floki": {:hex, :floki, "0.31.0", "f05ee8a8e6a3ced4e62beeb2c79a63bc8e12ab98fbaaf6e6a3d9b76b1278e23f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "b05afa372f5c345a5bf240ac25ea1f0f3d5fcfd7490ac0beeb4a203f9444891e"}, |   "floki": {:hex, :floki, "0.32.0", "f915dc15258bc997d49be1f5ef7d3992f8834d6f5695270acad17b41f5bcc8e2", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "1c5a91cae1fd8931c26a4826b5e2372c284813904c8bacb468b5de39c7ececbd"}, | ||||||
|   "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, |   "gettext": {:hex, :gettext, "0.19.0", "6909d61b38bb33339558f128f8af5913d5d5fe304a770217bf352b1620fb7ec4", [:mix], [], "hexpm", "3f7a274f52ebda9bb6655dfeda3d6b0dc4537ae51ce41dcccc7f73ca7379ad5e"}, | ||||||
|   "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, |   "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, | ||||||
|   "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, |   "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, | ||||||
|   "mime": {:hex, :mime, "2.0.0", "dea770ba85a5a17878c81fb395bfbfda46d8a882f5e93f9566ba47207ff4d956", [:mix], [], "hexpm", "78ba962513a989de60968db1bdbe26006417f804c6a94a53c32b29e892e3f1bc"}, |   "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, | ||||||
|   "phoenix": {:hex, :phoenix, "1.5.10", "3ee7d5c17ff9626d72d374d8fc8909bf00f4323fd15549fbe3abbbd38b5299c8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f9c2eaa5a8fe5a412610c6aa84ccdb6f3e92f333d4df7fbaeb0d5a157dbfb48d"}, |   "phoenix": {:hex, :phoenix, "1.6.6", "281c8ce8dccc9f60607346b72cdfc597c3dde134dd9df28dff08282f0b751754", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "807bd646e64cd9dc83db016199715faba72758e6db1de0707eef0a2da4924364"}, | ||||||
|   "phoenix_ecto": {:hex, :phoenix_ecto, "4.3.0", "2c69a452c2e0ee8c93345ae1cdc1696ef4877ff9cbb15c305def41960c3c4ebf", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0ac491924217550c8f42c81c1f390b5d81517d12ceaf9abf3e701156760a848e"}, |   "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, | ||||||
|   "phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"}, |   "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, | ||||||
|   "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.4.0", "87990e68b60213d7487e65814046f9a2bed4a67886c943270125913499b3e5c3", [:mix], [{:ecto_psql_extras, "~> 0.4.1 or ~> 0.5", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.15.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0 or ~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "8d52149e58188e9e4497cc0d8900ab94d9b66f96998ec38c47c7a4f8f4f50e57"}, |   "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.2", "0769470265eb13af01b5001b29cb935f4710d6adaa1ffc18417a570a337a2f0f", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5bc6c6b38a2ca8b5020b442322fcee6afd5e641637a0b1fb059d4bd89bc58e7b"}, | ||||||
|   "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [: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", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, |   "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [: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", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, | ||||||
|   "phoenix_live_view": {:hex, :phoenix_live_view, "0.15.7", "09720b8e5151b3ca8ef739cd7626d4feb987c69ba0b509c9bbdb861d5a365881", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a756cf662420272d0f1b3b908cce5222163b5a95aa9bab404f9d29aff53276e"}, |   "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.6", "3665f3ec426ac8d681cd7753ad4c85d2d247094dc4dc6add80dd6e3026045389", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "62f06d4bbfc4dc5595070bc338119ab08e8e67a011e2923f9366419622149b9c"}, | ||||||
|   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, |   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, | ||||||
|   "phx_gen_auth": {:hex, :phx_gen_auth, "0.7.0", "2e10e9527b6b71abbfbb4601c7dc4aa4fb9f2db6f9a6be457c468b7f2b0f6319", [:mix], [{:phoenix, "~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b9dc3e3b866e67c5db8f00f4a2adb28fc8636e794f78600e35aba0e55bdac209"}, |   "phoenix_view": {:hex, :phoenix_view, "1.1.0", "149f053830ec3c19a2a8a67c208885a26e4c2b92cc4a9d54e03b633d68ef9add", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "dd219f768b3d97a224ed11e8a83f4fd0f3bd490434d3950d7c51a2e597a762f1"}, | ||||||
|   "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"}, |   "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"}, | ||||||
|   "plug_cowboy": {:hex, :plug_cowboy, "2.5.1", "7cc96ff645158a94cf3ec9744464414f02287f832d6847079adfe0b58761cbd0", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "107d0a5865fa92bcb48e631cc0729ae9ccfa0a9f9a1bd8f01acb513abf1c2d64"}, |   "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, | ||||||
|   "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, |   "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, | ||||||
|   "postgrex": {:hex, :postgrex, "0.15.10", "2809dee1b1d76f7cbabe570b2a9285c2e7b41be60cf792f5f2804a54b838a067", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "1560ca427542f6b213f8e281633ae1a3b31cdbcd84ebd7f50628765b8f6132be"}, |   "postgrex": {:hex, :postgrex, "0.15.13", "7794e697481799aee8982688c261901de493eb64451feee6ea58207d7266d54a", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "3ffb76e1a97cfefe5c6a95632a27ffb67f28871c9741fb585f9d1c3cd2af70f1"}, | ||||||
|   "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, |   "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, | ||||||
|  |   "swoosh": {:hex, :swoosh, "1.6.0", "b7f17893ae46463e956a0e35d48293c231f2eab75d97e50232fb91a32d0cb63f", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "272e8550ac0af8a2c303c004b341810e5971cb3693de18ab12f2cc06feacaccb"}, | ||||||
|   "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, |   "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, | ||||||
|   "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, |   "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, | ||||||
|   "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, |   "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, | ||||||
|   "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"}, |   "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, | ||||||
| } | } | ||||||
|   | |||||||
| @@ -50,18 +50,18 @@ msgid "are still associated with this entry" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| ## From Ecto.Changeset.validate_length/3 | ## From Ecto.Changeset.validate_length/3 | ||||||
| msgid "should be %{count} character(s)" |  | ||||||
| msgid_plural "should be %{count} character(s)" |  | ||||||
| msgstr[0] "" |  | ||||||
| msgstr[1] "" |  | ||||||
|  |  | ||||||
| msgid "should have %{count} item(s)" | msgid "should have %{count} item(s)" | ||||||
| msgid_plural "should have %{count} item(s)" | msgid_plural "should have %{count} item(s)" | ||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| msgid "should be at least %{count} character(s)" | msgid "should be %{count} character(s)" | ||||||
| msgid_plural "should be at least %{count} character(s)" | msgid_plural "should be %{count} character(s)" | ||||||
|  | msgstr[0] "" | ||||||
|  | msgstr[1] "" | ||||||
|  |  | ||||||
|  | msgid "should be %{count} byte(s)" | ||||||
|  | msgid_plural "should be %{count} byte(s)" | ||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| @@ -70,8 +70,13 @@ msgid_plural "should have at least %{count} item(s)" | |||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| msgid "should be at most %{count} character(s)" | msgid "should be at least %{count} character(s)" | ||||||
| msgid_plural "should be at most %{count} character(s)" | msgid_plural "should be at least %{count} character(s)" | ||||||
|  | msgstr[0] "" | ||||||
|  | msgstr[1] "" | ||||||
|  |  | ||||||
|  | msgid "should be at least %{count} byte(s)" | ||||||
|  | msgid_plural "should be at least %{count} byte(s)" | ||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| @@ -80,6 +85,16 @@ msgid_plural "should have at most %{count} item(s)" | |||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
|  | msgid "should be at most %{count} character(s)" | ||||||
|  | msgid_plural "should be at most %{count} character(s)" | ||||||
|  | msgstr[0] "" | ||||||
|  | msgstr[1] "" | ||||||
|  |  | ||||||
|  | msgid "should be at most %{count} byte(s)" | ||||||
|  | msgid_plural "should be at most %{count} byte(s)" | ||||||
|  | msgstr[0] "" | ||||||
|  | msgstr[1] "" | ||||||
|  |  | ||||||
| ## From Ecto.Changeset.validate_number/3 | ## From Ecto.Changeset.validate_number/3 | ||||||
| msgid "must be less than %{number}" | msgid "must be less than %{number}" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
| defmodule CanneryWeb.HomeViewTest do | defmodule CanneryWeb.HomeViewTest do | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|  |  | ||||||
|  |   # When testing helpers, you may want to import Phoenix.HTML and | ||||||
|  |   # use functions such as safe_to_string() to convert the helper | ||||||
|  |   # result into an HTML string. | ||||||
|  |   # import Phoenix.HTML | ||||||
| end | end | ||||||
|   | |||||||
| @@ -29,12 +29,8 @@ defmodule CanneryWeb.ChannelCase do | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   setup tags do |   setup tags do | ||||||
|     :ok = Ecto.Adapters.SQL.Sandbox.checkout(Cannery.Repo) |     pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) | ||||||
|  |     on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) | ||||||
|     unless tags[:async] do |  | ||||||
|       Ecto.Adapters.SQL.Sandbox.mode(Cannery.Repo, {:shared, self()}) |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     :ok |     :ok | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -32,12 +32,8 @@ defmodule CanneryWeb.ConnCase do | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   setup tags do |   setup tags do | ||||||
|     :ok = Ecto.Adapters.SQL.Sandbox.checkout(Cannery.Repo) |     pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) | ||||||
|  |     on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) | ||||||
|     unless tags[:async] do |  | ||||||
|       Ecto.Adapters.SQL.Sandbox.mode(Cannery.Repo, {:shared, self()}) |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     {:ok, conn: Phoenix.ConnTest.build_conn()} |     {:ok, conn: Phoenix.ConnTest.build_conn()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,12 +28,8 @@ defmodule Cannery.DataCase do | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   setup tags do |   setup tags do | ||||||
|     :ok = Ecto.Adapters.SQL.Sandbox.checkout(Cannery.Repo) |     pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) | ||||||
|  |     on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) | ||||||
|     unless tags[:async] do |  | ||||||
|       Ecto.Adapters.SQL.Sandbox.mode(Cannery.Repo, {:shared, self()}) |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     :ok |     :ok | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user