Merge branch 'develop' into feature/title
This commit is contained in:
22 files changed
+991
-812
No files matched your search
@@ -1,6 +1,7 @@
|
||||
defmodule Ketbin.Pastes.Paste do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
@derive {Jason.Encoder, only: [:content, :is_url, :belongs_to]}
|
||||
|
||||
@primary_key {:id, :string, autogenerate: false}
|
||||
@derive {Phoenix.Param, key: :id}
|
||||
@@ -15,5 +16,6 @@ defmodule Ketbin.Pastes.Paste do
|
||||
paste
|
||||
|> cast(attrs, [:is_url, :content, :id, :belongs_to])
|
||||
|> validate_required([:is_url, :content])
|
||||
|> unique_constraint(:id, name: :pastes_pkey)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
defmodule KetbinWeb.Api.PasteController do
|
||||
use KetbinWeb, :controller
|
||||
|
||||
alias Ketbin.Pastes
|
||||
alias Ketbin.Pastes.Utils
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
[head | _tail] = String.split(id, ".")
|
||||
|
||||
# fetch paste from db
|
||||
paste = Pastes.get_paste!(head)
|
||||
render(conn, "paste.json", paste: paste)
|
||||
end
|
||||
|
||||
def create(%{assigns: %{current_user: current_user}} = conn, %{"paste" => paste_params}) do
|
||||
# generate phonetic key
|
||||
id = Utils.generate_key()
|
||||
|
||||
# check if content is a url
|
||||
is_url =
|
||||
Map.get(paste_params, "content")
|
||||
|> Utils.is_url?()
|
||||
|
||||
# put id and is_url values into changeset
|
||||
paste_params =
|
||||
Map.put(paste_params, "id", id)
|
||||
|> Map.put("is_url", is_url)
|
||||
|> Map.put("belongs_to", current_user && current_user.id)
|
||||
|
||||
# attempt to create a paste
|
||||
case Pastes.create_paste(paste_params) do
|
||||
# all good
|
||||
{:ok, paste} ->
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> render("paste.json", paste: paste)
|
||||
|
||||
# something went wrong, bail
|
||||
{:error, %Ecto.Changeset{} = _changeset} ->
|
||||
conn
|
||||
|> put_status(:internal_server_error)
|
||||
|> render("error.json")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,7 +38,7 @@ defmodule KetbinWeb.PageController do
|
||||
[head | tail] = String.split(id, ".")
|
||||
paste = Pastes.get_paste!(head)
|
||||
|
||||
render(conn, "show.html",
|
||||
render(conn, "shorten.html",
|
||||
paste: paste,
|
||||
show_edit: show_edit,
|
||||
extension: if(tail == [], do: "", else: tail),
|
||||
@@ -52,8 +52,12 @@ defmodule KetbinWeb.PageController do
|
||||
end
|
||||
|
||||
def create(%{assigns: %{current_user: current_user}} = conn, %{"paste" => paste_params}) do
|
||||
# generate phonetic key
|
||||
id = Utils.generate_key()
|
||||
# if custom url exists, use it as id, else generate phonetic id
|
||||
id =
|
||||
case Map.get(paste_params, "custom_url", "") do
|
||||
custom_url when custom_url != "" -> custom_url
|
||||
_ -> Utils.generate_key()
|
||||
end
|
||||
|
||||
# check if content is a url
|
||||
is_url =
|
||||
@@ -82,7 +86,13 @@ defmodule KetbinWeb.PageController do
|
||||
|
||||
# something went wrong, bail
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, "index.html", changeset: changeset)
|
||||
case changeset.errors[:id] do
|
||||
{"has already been taken", _} ->
|
||||
render(conn, "index.html", changeset: changeset, already_taken: true)
|
||||
|
||||
_ ->
|
||||
render(conn, "index.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ defmodule KetbinWeb.Endpoint do
|
||||
|
||||
plug Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
length: 10_000_000,
|
||||
pass: ["*/*"],
|
||||
json_decoder: Phoenix.json_library()
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ defmodule KetbinWeb.Router do
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
plug :fetch_session
|
||||
plug :fetch_current_user
|
||||
end
|
||||
|
||||
scope "/", KetbinWeb do
|
||||
@@ -42,6 +44,12 @@ defmodule KetbinWeb.Router do
|
||||
put "/:id", PageController, :update
|
||||
end
|
||||
|
||||
scope "/api", KetbinWeb.Api, as: :api do
|
||||
pipe_through :api
|
||||
|
||||
resources "/paste", PasteController, only: [:show, :index, :create]
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
# scope "/api", KetbinWeb do
|
||||
# pipe_through :api
|
||||
|
||||
@@ -9,6 +9,55 @@
|
||||
<% else %>
|
||||
<title>Katbin</title>
|
||||
<% end %>
|
||||
<title itemprop="name">Katbin</title>
|
||||
|
||||
<meta property="og:type" content="object">
|
||||
<meta property="og:title" content="Katbin">
|
||||
<meta property="og:image" content="/favicon.ico">
|
||||
|
||||
<meta name="twitter:title" content="Katbin">
|
||||
<meta itemprop="name" content="Katbin">
|
||||
<meta name="application-name" content="Katbin">
|
||||
<meta property="og:site_name" content="Katbin">
|
||||
<meta name="theme-color" content="#1a1a1a">
|
||||
<meta property="og:locale" content="en">
|
||||
<meta name="language" content="en">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@Spherical_Kat">
|
||||
<meta name="twitter:image" content="/favicon.ico">
|
||||
|
||||
<meta name="robots" content="index,follow">
|
||||
<meta name="googlebot" content="index,follow">
|
||||
<meta name="keywords" content="paste,pastebin,url,urlshortener,url-shortener,code,programming,bin,cat,kat,paste,share,save,login">
|
||||
<meta name="coverage" content="Worldwide">
|
||||
<meta name="distribution" content="Global">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="apple-mobile-web-app-title" content="Katbin">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
|
||||
<%= if assigns[:paste] do %>
|
||||
<meta name="description" content={@paste.content}>
|
||||
<meta itemprop="description" content={@paste.content}>
|
||||
<meta property="og:description" content={@paste.content}>
|
||||
<meta name="twitter:description" content={@paste.content}>
|
||||
|
||||
<meta name="url" content={"https://katb.in/#{@paste.id}"}>
|
||||
<meta name="twitter:url" content={"https://katb.in/#{@paste.id}"}>
|
||||
<meta property="og:url" content={"https://katb.in/#{@paste.id}"}>
|
||||
<% else %>
|
||||
<meta name="description" content="Paste, save, share! A pastebin and URL shortener for all your needs.">
|
||||
<meta property="og:description" content="Paste, save, share! A pastebin and URL shortener for all your needs.">
|
||||
<meta itemprop="og:description" content="Paste, save, share! A pastebin and URL shortener for all your needs.">
|
||||
<meta name="twitter:description" content="Paste, save, share! A pastebin and URL shortener for all your needs.">
|
||||
|
||||
<meta name="url" content="https://katb.in">
|
||||
<meta name="twitter:url" content="https://katb.in">
|
||||
<meta property="og:url" content="https://katb.in">
|
||||
<% end %>
|
||||
|
||||
<link rel="stylesheet" href={ Routes.static_path(@conn, "/assets/app.css") }/>
|
||||
<script defer type="text/javascript" src={ Routes.static_path(@conn, "/assets/app.js") }></script>
|
||||
</head>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<%= render "form.html", Map.put(assigns, :action, Routes.page_path(@conn, :update, @paste)) %>
|
||||
<%= render "form.html", Map.put(assigns, :action, Routes.page_path(@conn, :update, @paste)) |> Map.put(:is_edit, true) %>
|
||||
@@ -13,9 +13,20 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= if assigns[:already_taken] do %>
|
||||
<div class="w-full text-center bg-amber">
|
||||
<p>This custom URL has already been taken.</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="w-full h-full">
|
||||
<%= textarea f, :content, [class: "w-full h-full px-6 py-4 outline-none bg-light-grey font-bold resize-none", placeholder: "> Paste, save, share! (Pasting just a URL will shorten it!)"] %>
|
||||
<div class="flex absolute top-0 right-0 p-4">
|
||||
<%= if @current_user && !assigns[:is_edit] do %>
|
||||
<div>
|
||||
<%= text_input f, :custom_url, [class: "px-2 mr-2 outline-none text-black px-2 py-1", placeholder: "Custom URL"] %>
|
||||
</div>
|
||||
<% end %>
|
||||
<button type="submit">
|
||||
<svg
|
||||
class="h-6 w-6 cursor-pointer fill-current text-white hover:text-amber"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="flex relative flex-col w-full h-full">
|
||||
<div class="flex absolute top-0 right-0 p-4">
|
||||
<%= if @show_edit do%>
|
||||
<a href={ Routes.page_path(@conn, :edit, @paste.id) } class="text-white hover:text-amber">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-6 w-6 cursor-pointer fill-current">
|
||||
<path d="M3 17.46v3.04c0 .28.22.5.5.5h3.04c.13 0 .26-.05.35-.15L17.81 9.94l-3.75-3.75L3.15 17.1c-.1.1-.15.22-.15.36zM20.71 7.04a.996.996 0 0 0 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="break-word px-6 py-4 h-full w-full overflow-y-auto">
|
||||
<span>
|
||||
Your shortened url is: <a href={Routes.page_path(@conn, :show, @paste.id) }>https://katb.in/<%= @paste.id %></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,18 @@
|
||||
defmodule KetbinWeb.Api.PasteView do
|
||||
use KetbinWeb, :view
|
||||
|
||||
def render("paste.json", %{paste: paste}) do
|
||||
%{
|
||||
id: paste.id,
|
||||
content: paste.content,
|
||||
is_url: paste.is_url
|
||||
}
|
||||
end
|
||||
|
||||
def render("error.json", _assigns) do
|
||||
%{
|
||||
success: false,
|
||||
msg: "Something went wrong"
|
||||
}
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user