forked from shibao/cannery
		
	update to 1.6
This commit is contained in:
		@@ -10,61 +10,7 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
 | 
			
		||||
 | 
			
		||||
@import "components";
 | 
			
		||||
 | 
			
		||||
/* LiveView specific classes for your customizations */
 | 
			
		||||
.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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.phx-modal {
 | 
			
		||||
  opacity: 1!important;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  background-color: rgb(0,0,0);
 | 
			
		||||
  background-color: rgba(0,0,0,0.4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.phx-modal-content {
 | 
			
		||||
  background-color: #fefefe;
 | 
			
		||||
  margin: 15% 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Alerts and form errors */
 | 
			
		||||
/* Alerts and form errors used by phx.new */
 | 
			
		||||
.alert {
 | 
			
		||||
  padding: 15px;
 | 
			
		||||
  margin-bottom: 20px;
 | 
			
		||||
@@ -96,4 +42,88 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
 | 
			
		||||
  color: #a94442;
 | 
			
		||||
  display: block;
 | 
			
		||||
  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,21 +1,30 @@
 | 
			
		||||
// We need to import the CSS so that webpack will load it.
 | 
			
		||||
// The MiniCssExtractPlugin is used to separate it out into
 | 
			
		||||
// its own CSS file.
 | 
			
		||||
// We import the CSS which is extracted to its own file by esbuild.
 | 
			
		||||
// Remove this line if you add a your own CSS build pipeline (e.g postcss).
 | 
			
		||||
import "../css/app.scss"
 | 
			
		||||
 | 
			
		||||
// webpack automatically bundles all modules in your
 | 
			
		||||
// entry points. Those entry points can be configured
 | 
			
		||||
// in "webpack.config.js".
 | 
			
		||||
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
 | 
			
		||||
// to get started and then uncomment the line below.
 | 
			
		||||
// import "./user_socket.js"
 | 
			
		||||
 | 
			
		||||
// You can include dependencies in two ways.
 | 
			
		||||
//
 | 
			
		||||
// Import deps with the dep name or local files with a relative path, for example:
 | 
			
		||||
// The simplest option is to put them in assets/vendor and
 | 
			
		||||
// import them using relative paths:
 | 
			
		||||
//
 | 
			
		||||
//     import {Socket} from "phoenix"
 | 
			
		||||
//     import socket from "./socket"
 | 
			
		||||
//     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 topbar from "topbar"
 | 
			
		||||
import {LiveSocket} from "phoenix_live_view"
 | 
			
		||||
import topbar from "../vendor/topbar"
 | 
			
		||||
 | 
			
		||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
 | 
			
		||||
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
 | 
			
		||||
@@ -33,4 +42,3 @@ liveSocket.connect()
 | 
			
		||||
// >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session
 | 
			
		||||
// >> liveSocket.disableLatencySim()
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										439
									
								
								assets/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										439
									
								
								assets/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										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));
 | 
			
		||||
		Reference in New Issue
	
	Block a user