mirror of
https://github.com/ash-project/ash_hq.git
synced 2024-09-19 21:03:30 +12:00
improvement: upgrade to 3.0
This commit is contained in:
parent
6a943f22d7
commit
2221ef824d
59 changed files with 381 additions and 548 deletions
|
@ -24,34 +24,43 @@ import { LiveSocket } from "phoenix_live_view";
|
||||||
import topbar from "../vendor/topbar";
|
import topbar from "../vendor/topbar";
|
||||||
|
|
||||||
function setCookie(name, value) {
|
function setCookie(name, value) {
|
||||||
document.cookie = name + "=" + value + ";path=/;" + "expires=Fri, 31 Dec 9999 23:59:59 GMT;";
|
document.cookie =
|
||||||
|
name + "=" + value + ";path=/;" + "expires=Fri, 31 Dec 9999 23:59:59 GMT;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCookie(name) {
|
function getCookie(name) {
|
||||||
const cookie = document.cookie.split("; ").find((row) => row.startsWith(name + "="))
|
const cookie = document.cookie
|
||||||
|
.split("; ")
|
||||||
|
.find((row) => row.startsWith(name + "="));
|
||||||
if (cookie) {
|
if (cookie) {
|
||||||
return cookie.split("=")[1]
|
return cookie.split("=")[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cookiesAreAllowed() {
|
function cookiesAreAllowed() {
|
||||||
return getCookie("cookieconsent_status") === "allow"
|
return getCookie("cookieconsent_status") === "allow";
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_platform() {
|
function get_platform() {
|
||||||
// 2022 way of detecting. Note : this userAgentData feature is available only in secure contexts (HTTPS)
|
// 2022 way of detecting. Note : this userAgentData feature is available only in secure contexts (HTTPS)
|
||||||
if (typeof navigator.userAgentData !== 'undefined' && navigator.userAgentData != null) {
|
if (
|
||||||
|
typeof navigator.userAgentData !== "undefined" &&
|
||||||
|
navigator.userAgentData != null
|
||||||
|
) {
|
||||||
return navigator.userAgentData.platform;
|
return navigator.userAgentData.platform;
|
||||||
}
|
}
|
||||||
// Deprecated but still works for most of the browser
|
// Deprecated but still works for most of the browser
|
||||||
if (typeof navigator.platform !== 'undefined') {
|
if (typeof navigator.platform !== "undefined") {
|
||||||
if (typeof navigator.userAgent !== 'undefined' && /android/.test(navigator.userAgent.toLowerCase())) {
|
if (
|
||||||
|
typeof navigator.userAgent !== "undefined" &&
|
||||||
|
/android/.test(navigator.userAgent.toLowerCase())
|
||||||
|
) {
|
||||||
// android device's navigator.platform is often set as 'linux', so let's use userAgent for them
|
// android device's navigator.platform is often set as 'linux', so let's use userAgent for them
|
||||||
return 'android';
|
return "android";
|
||||||
}
|
}
|
||||||
return navigator.platform;
|
return navigator.platform;
|
||||||
}
|
}
|
||||||
return 'unknown';
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
let platform = get_platform();
|
let platform = get_platform();
|
||||||
|
@ -110,13 +119,15 @@ let scrolled = false;
|
||||||
|
|
||||||
Hooks.RightNav = {
|
Hooks.RightNav = {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.intersectionObserver =
|
this.intersectionObserver = new IntersectionObserver(
|
||||||
new IntersectionObserver((entries) =>
|
(entries) => this.onScrollChange(entries),
|
||||||
this.onScrollChange(entries), { rootMargin: "-10% 0px -89% 0px" }
|
{ rootMargin: "-10% 0px -89% 0px" },
|
||||||
);
|
);
|
||||||
|
|
||||||
this.observeElements()
|
this.observeElements();
|
||||||
window.addEventListener("hashchange", (event) => { this.handleHashChange(); });
|
window.addEventListener("hashchange", (event) => {
|
||||||
|
this.handleHashChange();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
updated() {
|
updated() {
|
||||||
this.intersectionObserver.disconnect();
|
this.intersectionObserver.disconnect();
|
||||||
|
@ -129,7 +140,9 @@ Hooks.RightNav = {
|
||||||
},
|
},
|
||||||
onScrollChange(entries) {
|
onScrollChange(entries) {
|
||||||
// Wait for scrolling from initial page load to complete
|
// Wait for scrolling from initial page load to complete
|
||||||
if (!scrolled) { return; }
|
if (!scrolled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (entry of entries) {
|
for (entry of entries) {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
|
@ -139,19 +152,21 @@ Hooks.RightNav = {
|
||||||
},
|
},
|
||||||
handleHashChange() {
|
handleHashChange() {
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
this.setAriaCurrent(window.location.hash.substring(1))
|
this.setAriaCurrent(window.location.hash.substring(1));
|
||||||
|
|
||||||
// Disable the insersection observer for 1s while the browser
|
// Disable the insersection observer for 1s while the browser
|
||||||
// scrolls the selected element to the top.
|
// scrolls the selected element to the top.
|
||||||
scrolled = false;
|
scrolled = false;
|
||||||
setTimeout(() => { scrolled = true }, 1000);
|
setTimeout(() => {
|
||||||
|
scrolled = true;
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setAriaCurrent(id) {
|
setAriaCurrent(id) {
|
||||||
const el = document.getElementById("right-nav-" + id);
|
const el = document.getElementById("right-nav-" + id);
|
||||||
if (el) {
|
if (el) {
|
||||||
for (elem of document.querySelectorAll('#right-nav a[aria-current]')) {
|
for (elem of document.querySelectorAll("#right-nav a[aria-current]")) {
|
||||||
elem.removeAttribute('aria-current');
|
elem.removeAttribute("aria-current");
|
||||||
}
|
}
|
||||||
el.setAttribute("aria-current", "true");
|
el.setAttribute("aria-current", "true");
|
||||||
}
|
}
|
||||||
|
@ -201,9 +216,9 @@ window.addEventListener("phx:page-loading-start", ({ detail }) => {
|
||||||
scrolled = false;
|
scrolled = false;
|
||||||
|
|
||||||
// close mobile sidebar on navigation
|
// close mobile sidebar on navigation
|
||||||
mobileSideBar = document.getElementById("mobile-sidebar-hide")
|
mobileSideBar = document.getElementById("mobile-sidebar-hide");
|
||||||
if (mobileSideBar) {
|
if (mobileSideBar) {
|
||||||
mobileSideBar.click()
|
mobileSideBar.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!topBarScheduled) {
|
if (!topBarScheduled) {
|
||||||
|
@ -219,13 +234,17 @@ window.addEventListener("phx:page-loading-stop", ({ detail }) => {
|
||||||
if (detail.kind === "initial" && window.location.hash) {
|
if (detail.kind === "initial" && window.location.hash) {
|
||||||
scrollEl = document.getElementById(window.location.hash.substring(1));
|
scrollEl = document.getElementById(window.location.hash.substring(1));
|
||||||
} else if (detail.kind == "patch" && !window.location.hash) {
|
} else if (detail.kind == "patch" && !window.location.hash) {
|
||||||
scrollEl = document.querySelector("#docs-window .nav-anchor") || document.querySelector("#docs-window h1");
|
scrollEl =
|
||||||
|
document.querySelector("#docs-window .nav-anchor") ||
|
||||||
|
document.querySelector("#docs-window h1");
|
||||||
}
|
}
|
||||||
if (scrollEl) {
|
if (scrollEl) {
|
||||||
Hooks.RightNav.setAriaCurrent(scrollEl.id);
|
Hooks.RightNav.setAriaCurrent(scrollEl.id);
|
||||||
// Not using scroll polyfill here - doesn't respect scroll-padding-top CSS
|
// Not using scroll polyfill here - doesn't respect scroll-padding-top CSS
|
||||||
scrollEl.scrollIntoView({ block: 'start' })
|
scrollEl.scrollIntoView({ block: "start" });
|
||||||
setTimeout(() => { scrolled = true; }, 1000);
|
setTimeout(() => {
|
||||||
|
scrolled = true;
|
||||||
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
scrolled = true;
|
scrolled = true;
|
||||||
}
|
}
|
||||||
|
@ -243,13 +262,6 @@ window.addEventListener("phx:js:scroll-to", (e) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("phx:selected-types", (e) => {
|
|
||||||
if (cookiesAreAllowed()) {
|
|
||||||
const cookie = e.detail.types.join(",");
|
|
||||||
setCookies("selected_types", cookie)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener("keydown", (event) => {
|
window.addEventListener("keydown", (event) => {
|
||||||
if ((event.metaKey || event.ctrlKey) && event.key === "k") {
|
if ((event.metaKey || event.ctrlKey) && event.key === "k") {
|
||||||
document.getElementById("search-button").click();
|
document.getElementById("search-button").click();
|
||||||
|
@ -258,9 +270,11 @@ window.addEventListener("keydown", (event) => {
|
||||||
});
|
});
|
||||||
window.addEventListener("keydown", (event) => {
|
window.addEventListener("keydown", (event) => {
|
||||||
if (event.key === "Escape") {
|
if (event.key === "Escape") {
|
||||||
const closeSearchVersions = document.getElementById("close-search-versions");
|
const closeSearchVersions = document.getElementById(
|
||||||
|
"close-search-versions",
|
||||||
|
);
|
||||||
if (closeSearchVersions && closeSearchVersions.offsetParent !== null) {
|
if (closeSearchVersions && closeSearchVersions.offsetParent !== null) {
|
||||||
closeSearchVersions.click()
|
closeSearchVersions.click();
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("close-search").click();
|
document.getElementById("close-search").click();
|
||||||
}
|
}
|
||||||
|
@ -288,7 +302,7 @@ liveSocket.connect();
|
||||||
// >> liveSocket.disableLatencySim()
|
// >> liveSocket.disableLatencySim()
|
||||||
window.liveSocket = liveSocket;
|
window.liveSocket = liveSocket;
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function () {
|
||||||
window.cookieconsent.initialise({
|
window.cookieconsent.initialise({
|
||||||
content: {
|
content: {
|
||||||
message:
|
message:
|
||||||
|
|
|
@ -25,7 +25,7 @@ config :ash_appsignal,
|
||||||
config :appsignal, :config, revision: "test-4"
|
config :appsignal, :config, revision: "test-4"
|
||||||
|
|
||||||
config :ash_hq,
|
config :ash_hq,
|
||||||
ash_apis: [
|
ash_domains: [
|
||||||
AshHq.Accounts,
|
AshHq.Accounts,
|
||||||
AshHq.Blog,
|
AshHq.Blog,
|
||||||
AshHq.Docs,
|
AshHq.Docs,
|
||||||
|
@ -40,7 +40,6 @@ config :ash_hq, AshHq.Repo,
|
||||||
|
|
||||||
config :spark, :formatter,
|
config :spark, :formatter,
|
||||||
remove_parens?: true,
|
remove_parens?: true,
|
||||||
"Ash.Registry": [],
|
|
||||||
"Ash.Resource": [
|
"Ash.Resource": [
|
||||||
type: Ash.Resource,
|
type: Ash.Resource,
|
||||||
section_order: [
|
section_order: [
|
||||||
|
|
|
@ -2,13 +2,10 @@ defmodule AshHq.Accounts do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Handles user and user token related operations/state
|
Handles user and user token related operations/state
|
||||||
"""
|
"""
|
||||||
use Ash.Api, otp_app: :ash_hq
|
use Ash.Domain, otp_app: :ash_hq
|
||||||
|
|
||||||
authorization do
|
|
||||||
authorize :by_default
|
|
||||||
end
|
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
registry AshHq.Accounts.Registry
|
resource AshHq.Accounts.User
|
||||||
|
resource AshHq.Accounts.UserToken
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
defmodule AshHq.Accounts.Registry do
|
|
||||||
@moduledoc false
|
|
||||||
|
|
||||||
use Ash.Registry,
|
|
||||||
extensions: [Ash.Registry.ResourceValidations]
|
|
||||||
|
|
||||||
entries do
|
|
||||||
entry AshHq.Accounts.User
|
|
||||||
entry AshHq.Accounts.UserToken
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,26 +0,0 @@
|
||||||
defmodule AshHq.Accounts.User.Changes.RemoveAllTokens do
|
|
||||||
@moduledoc """
|
|
||||||
Removes all tokens for a given user.
|
|
||||||
|
|
||||||
Since Ash does not yet support bulk actions, this goes straight to the data layer.
|
|
||||||
"""
|
|
||||||
use Ash.Resource.Change
|
|
||||||
require Ash.Query
|
|
||||||
|
|
||||||
def change(changeset, _opts, _context) do
|
|
||||||
Ash.Changeset.after_action(
|
|
||||||
changeset,
|
|
||||||
fn _changeset, user ->
|
|
||||||
{:ok, query} =
|
|
||||||
AshHq.Accounts.UserToken
|
|
||||||
|> Ash.Query.filter(user_id == ^user.id)
|
|
||||||
|> Ash.Query.data_layer_query()
|
|
||||||
|
|
||||||
AshHq.Repo.delete_all(query)
|
|
||||||
|
|
||||||
{:ok, user}
|
|
||||||
end,
|
|
||||||
prepend?: true
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,25 +6,5 @@ defmodule AshHq.Accounts.User.Policies do
|
||||||
policy action(:read) do
|
policy action(:read) do
|
||||||
authorize_if(expr(id == ^actor(:id)))
|
authorize_if(expr(id == ^actor(:id)))
|
||||||
end
|
end
|
||||||
|
|
||||||
policy action(:update_email) do
|
|
||||||
description("A logged in user can update their email")
|
|
||||||
authorize_if(expr(id == ^actor(:id)))
|
|
||||||
end
|
|
||||||
|
|
||||||
policy action(:resend_confirmation_instructions) do
|
|
||||||
description("A logged in user can request an email confirmation")
|
|
||||||
authorize_if(expr(id == ^actor(:id)))
|
|
||||||
end
|
|
||||||
|
|
||||||
policy action(:change_password) do
|
|
||||||
description("A logged in user can reset their password")
|
|
||||||
authorize_if(expr(id == ^actor(:id)))
|
|
||||||
end
|
|
||||||
|
|
||||||
policy action(:update_merch_settings) do
|
|
||||||
description("A logged in user can update their merch settings")
|
|
||||||
authorize_if(expr(id == ^actor(:id)))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@ defmodule AshHq.Accounts.User do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Accounts,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
fragments: [AshHq.Accounts.User.Policies]
|
fragments: [AshHq.Accounts.User.Policies]
|
||||||
|
|
||||||
|
@ -11,130 +12,6 @@ defmodule AshHq.Accounts.User do
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
defaults [:read]
|
defaults [:read]
|
||||||
|
|
||||||
# create :register_with_github do
|
|
||||||
# argument :user_info, :map do
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# argument :oauth_tokens, :map do
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# change fn changeset, _ ->
|
|
||||||
# user_info = Ash.Changeset.get_argument(changeset, :user_info)
|
|
||||||
|
|
||||||
# changeset =
|
|
||||||
# if user_info["email_verified"] do
|
|
||||||
# Ash.Changeset.force_change_attribute(
|
|
||||||
# changeset,
|
|
||||||
# :confirmed_at,
|
|
||||||
# Ash.Changeset.get_attribute(changeset, :confirmed_at) || DateTime.utc_now()
|
|
||||||
# )
|
|
||||||
# else
|
|
||||||
# changeset
|
|
||||||
# end
|
|
||||||
|
|
||||||
# changeset
|
|
||||||
# |> Ash.Changeset.change_attribute(:email, Map.get(user_info, "email"))
|
|
||||||
# |> Ash.Changeset.change_attribute(:github_info, user_info)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# change AshAuthentication.GenerateTokenChange
|
|
||||||
# upsert? true
|
|
||||||
# upsert_identity :unique_email
|
|
||||||
# end
|
|
||||||
|
|
||||||
# update :change_password do
|
|
||||||
# accept []
|
|
||||||
|
|
||||||
# argument :current_password, :string do
|
|
||||||
# sensitive? true
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# argument :password, :string do
|
|
||||||
# sensitive? true
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# argument :password_confirmation, :string do
|
|
||||||
# sensitive? true
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# change set_context(%{strategy_name: :password})
|
|
||||||
|
|
||||||
# validate confirm(:password, :password_confirmation)
|
|
||||||
|
|
||||||
# validate {AshAuthentication.Strategy.Password.PasswordValidation,
|
|
||||||
# strategy_name: :password, password_argument: :current_password} do
|
|
||||||
# only_when_valid? true
|
|
||||||
# before_action? true
|
|
||||||
# end
|
|
||||||
|
|
||||||
# change AshAuthentication.Strategy.Password.HashPasswordChange
|
|
||||||
# end
|
|
||||||
|
|
||||||
# update :update_email do
|
|
||||||
# accept [:email]
|
|
||||||
|
|
||||||
# argument :current_password, :string do
|
|
||||||
# sensitive? true
|
|
||||||
# allow_nil? false
|
|
||||||
# end
|
|
||||||
|
|
||||||
# change set_context(%{strategy_name: :password})
|
|
||||||
|
|
||||||
# validate {AshAuthentication.Strategy.Password.PasswordValidation,
|
|
||||||
# password_argument: :current_password} do
|
|
||||||
# only_when_valid? true
|
|
||||||
# before_action? true
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
# update :resend_confirmation_instructions do
|
|
||||||
# accept []
|
|
||||||
|
|
||||||
# change fn changeset, _context ->
|
|
||||||
# Ash.Changeset.before_action(changeset, fn changeset ->
|
|
||||||
# case AshHq.Accounts.UserToken.email_token_for_user(changeset.data.id,
|
|
||||||
# authorize?: false
|
|
||||||
# ) do
|
|
||||||
# {:ok, %{extra_data: %{"email" => changing_to}}} ->
|
|
||||||
# temp_changeset = %{
|
|
||||||
# changeset
|
|
||||||
# | attributes: Map.put(changeset.attributes, :email, changing_to)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# strategy = AshAuthentication.Info.strategy!(changeset.resource, :confirm)
|
|
||||||
|
|
||||||
# {:ok, token} =
|
|
||||||
# AshAuthentication.AddOn.Confirmation.confirmation_token(
|
|
||||||
# strategy,
|
|
||||||
# temp_changeset,
|
|
||||||
# changeset.data
|
|
||||||
# )
|
|
||||||
|
|
||||||
# AshHq.Accounts.User.Senders.SendConfirmationEmail.send(changeset.data, token, [])
|
|
||||||
|
|
||||||
# changeset
|
|
||||||
|
|
||||||
# _ ->
|
|
||||||
# Ash.Changeset.add_error(changeset, "Could not determine what email to use")
|
|
||||||
# end
|
|
||||||
# end)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
# update :update_merch_settings do
|
|
||||||
# argument :address, :string
|
|
||||||
# argument :name, :string
|
|
||||||
|
|
||||||
# accept [:shirt_size]
|
|
||||||
# change set_attribute(:encrypted_address, arg(:address))
|
|
||||||
# change set_attribute(:encrypted_name, arg(:name))
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
|
@ -146,7 +23,7 @@ defmodule AshHq.Accounts.User do
|
||||||
max_length: 160
|
max_length: 160
|
||||||
]
|
]
|
||||||
|
|
||||||
attribute :hashed_password, :string, private?: true, sensitive?: true
|
attribute :hashed_password, :string, sensitive?: true
|
||||||
|
|
||||||
attribute :encrypted_name, :string
|
attribute :encrypted_name, :string
|
||||||
attribute :encrypted_address, :string
|
attribute :encrypted_address, :string
|
||||||
|
@ -160,7 +37,6 @@ defmodule AshHq.Accounts.User do
|
||||||
relationships do
|
relationships do
|
||||||
has_one :token, AshHq.Accounts.UserToken do
|
has_one :token, AshHq.Accounts.UserToken do
|
||||||
destination_attribute :user_id
|
destination_attribute :user_id
|
||||||
private? true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -169,12 +45,6 @@ defmodule AshHq.Accounts.User do
|
||||||
repo AshHq.Repo
|
repo AshHq.Repo
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Accounts
|
|
||||||
define :resend_confirmation_instructions
|
|
||||||
define :register_with_password, args: [:email, :password, :password_confirmation]
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description """
|
description """
|
||||||
Represents the user of a system.
|
Represents the user of a system.
|
||||||
|
@ -188,9 +58,6 @@ defmodule AshHq.Accounts.User do
|
||||||
end
|
end
|
||||||
|
|
||||||
changes do
|
changes do
|
||||||
change AshHq.Accounts.User.Changes.RemoveAllTokens,
|
|
||||||
where: [action_is(:password_reset_with_password)]
|
|
||||||
|
|
||||||
change {AshHq.Changes.Encrypt, fields: [:encrypted_address, :encrypted_name]}
|
change {AshHq.Changes.Encrypt, fields: [:encrypted_address, :encrypted_name]}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,27 +2,16 @@ defmodule AshHq.Accounts.UserToken do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Accounts,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
authorizers: [Ash.Policy.Authorizer]
|
authorizers: [Ash.Policy.Authorizer]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
defaults [:read, :destroy]
|
defaults [:read]
|
||||||
|
|
||||||
read :email_token_for_user do
|
|
||||||
get? true
|
|
||||||
|
|
||||||
argument :user_id, :uuid do
|
|
||||||
allow_nil? false
|
|
||||||
end
|
|
||||||
|
|
||||||
prepare build(sort: [updated_at: :desc], limit: 1)
|
|
||||||
|
|
||||||
filter expr(purpose == "confirm" and not is_nil(extra_data[:email]))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
token do
|
attributes do
|
||||||
api AshHq.Accounts
|
uuid_primary_key :id
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
@ -32,8 +21,7 @@ defmodule AshHq.Accounts.UserToken do
|
||||||
policies do
|
policies do
|
||||||
policy always() do
|
policy always() do
|
||||||
description """
|
description """
|
||||||
There are currently no usages of user tokens resource that should be publicly
|
There are currently no usages of user tokens resource that should be publicly accessible.
|
||||||
accessible, they should all be using authorize?: false.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
forbid_if always()
|
forbid_if always()
|
||||||
|
@ -49,30 +37,9 @@ defmodule AshHq.Accounts.UserToken do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Accounts
|
|
||||||
define :destroy
|
|
||||||
define :email_token_for_user, args: [:user_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description """
|
description """
|
||||||
Represents a token allowing a user to log in, reset their password, or confirm their email.
|
Represents a token allowing a user to log in, reset their password, or confirm their email.
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
changes do
|
|
||||||
change fn changeset, _ ->
|
|
||||||
case changeset.context[:ash_authentication][:user] do
|
|
||||||
nil ->
|
|
||||||
changeset
|
|
||||||
|
|
||||||
user ->
|
|
||||||
Ash.Changeset.manage_relationship(changeset, :user, user,
|
|
||||||
type: :append_and_remove
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
on: [:create]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
defmodule AshHq.ApiHelpers do
|
|
||||||
@moduledoc false
|
|
||||||
defmacro __using__(_) do
|
|
||||||
quote do
|
|
||||||
def stream(query, opts \\ []) do
|
|
||||||
api = __MODULE__
|
|
||||||
query = Ash.Query.to_query(query)
|
|
||||||
|
|
||||||
query =
|
|
||||||
if query.action do
|
|
||||||
query
|
|
||||||
else
|
|
||||||
Ash.Query.for_read(
|
|
||||||
query,
|
|
||||||
Ash.Resource.Info.primary_action!(query.resource, :read).name
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
Stream.resource(
|
|
||||||
fn -> nil end,
|
|
||||||
fn
|
|
||||||
false ->
|
|
||||||
{:halt, nil}
|
|
||||||
|
|
||||||
after_keyset ->
|
|
||||||
if is_nil(query.action.pagination) || !query.action.pagination.keyset? do
|
|
||||||
raise "Keyset pagination must be enabled"
|
|
||||||
end
|
|
||||||
|
|
||||||
keyset = if after_keyset != nil, do: [after: after_keyset], else: []
|
|
||||||
page_opts = Keyword.merge([limit: 100], keyset)
|
|
||||||
|
|
||||||
opts =
|
|
||||||
[
|
|
||||||
page: page_opts
|
|
||||||
]
|
|
||||||
|> Keyword.merge(opts)
|
|
||||||
|
|
||||||
case api.read!(query, opts) do
|
|
||||||
%{more?: true, results: results} ->
|
|
||||||
{results, List.last(results).__metadata__.keyset}
|
|
||||||
|
|
||||||
%{results: results} ->
|
|
||||||
{results, false}
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
& &1
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -7,6 +7,7 @@ defmodule AshHq.Application do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
|
:erlang.system_flag(:backtrace_depth, 1000)
|
||||||
Appsignal.Phoenix.LiveView.attach()
|
Appsignal.Phoenix.LiveView.attach()
|
||||||
|
|
||||||
# topologies = Application.get_env(:libcluster, :topologies) || []
|
# topologies = Application.get_env(:libcluster, :topologies) || []
|
||||||
|
@ -48,8 +49,8 @@ defmodule AshHq.Application do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp oban_worker do
|
defp oban_worker do
|
||||||
apis = Application.fetch_env!(:ash_hq, :ash_apis)
|
domains = Application.fetch_env!(:ash_hq, :ash_domains)
|
||||||
config = Application.fetch_env!(:ash_hq, Oban)
|
config = Application.fetch_env!(:ash_hq, Oban)
|
||||||
{Oban, AshOban.config(apis, config)}
|
{Oban, AshOban.config(domains, config)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule AshHq.Blog do
|
defmodule AshHq.Blog do
|
||||||
@moduledoc "An api for interacting with the blog"
|
@moduledoc "A domain for interacting with the blog"
|
||||||
use Ash.Api,
|
use Ash.Domain,
|
||||||
extensions: [AshAdmin.Api]
|
extensions: [AshAdmin.Domain]
|
||||||
|
|
||||||
admin do
|
admin do
|
||||||
show? true
|
show? true
|
||||||
|
@ -9,6 +9,7 @@ defmodule AshHq.Blog do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
registry AshHq.Blog.Registry
|
resource AshHq.Blog.Post
|
||||||
|
resource AshHq.Blog.Tag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
defmodule AshHq.Blog.Registry do
|
|
||||||
@moduledoc "The resources used in the blog"
|
|
||||||
use Ash.Registry,
|
|
||||||
extensions: [Ash.Registry.ResourceValidations]
|
|
||||||
|
|
||||||
entries do
|
|
||||||
entry AshHq.Blog.Post
|
|
||||||
entry AshHq.Blog.Tag
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule AshHq.Blog.Post do
|
defmodule AshHq.Blog.Post do
|
||||||
@moduledoc "A blog post. Uses the AshBlog data layer and therefore is static"
|
@moduledoc "A blog post. Uses the AshBlog data layer and therefore is static"
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Blog,
|
||||||
otp_app: :ash_hq,
|
otp_app: :ash_hq,
|
||||||
data_layer: AshBlog.DataLayer,
|
data_layer: AshBlog.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.RenderMarkdown, AshAdmin.Resource]
|
extensions: [AshHq.Docs.Extensions.RenderMarkdown, AshAdmin.Resource]
|
||||||
|
@ -22,6 +23,7 @@ defmodule AshHq.Blog.Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update]
|
defaults [:create, :read, :update]
|
||||||
|
|
||||||
read :published do
|
read :published do
|
||||||
|
@ -52,11 +54,13 @@ defmodule AshHq.Blog.Post do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :tag_line, :string do
|
attribute :tag_line, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints max_length: 250
|
constraints max_length: 250
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :tag_names, {:array, :ci_string} do
|
attribute :tag_names, {:array, :ci_string} do
|
||||||
|
public? true
|
||||||
constraints items: [
|
constraints items: [
|
||||||
match: ~r/^[a-zA-Z]*$/,
|
match: ~r/^[a-zA-Z]*$/,
|
||||||
casing: :lower
|
casing: :lower
|
||||||
|
@ -64,10 +68,12 @@ defmodule AshHq.Blog.Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :author, :string do
|
attribute :author, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :body_html, :string do
|
attribute :body_html, :string do
|
||||||
|
public? true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -76,6 +82,7 @@ defmodule AshHq.Blog.Post do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :tags, AshHq.Blog.Tag do
|
has_many :tags, AshHq.Blog.Tag do
|
||||||
|
public? true
|
||||||
manual fn posts, %{query: query} ->
|
manual fn posts, %{query: query} ->
|
||||||
all_tags = Enum.flat_map(posts, &(&1.tag_names || []))
|
all_tags = Enum.flat_map(posts, &(&1.tag_names || []))
|
||||||
|
|
||||||
|
@ -83,7 +90,7 @@ defmodule AshHq.Blog.Post do
|
||||||
query
|
query
|
||||||
|> Ash.Query.unset([:limit, :offset])
|
|> Ash.Query.unset([:limit, :offset])
|
||||||
|> Ash.Query.filter(name in ^all_tags)
|
|> Ash.Query.filter(name in ^all_tags)
|
||||||
|> AshHq.Blog.read!()
|
|> Ash.read!()
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
Map.new(posts, fn post ->
|
Map.new(posts, fn post ->
|
||||||
|
@ -94,7 +101,6 @@ defmodule AshHq.Blog.Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Blog
|
|
||||||
define :published
|
define :published
|
||||||
define :by_slug, args: [:slug]
|
define :by_slug, args: [:slug]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule AshHq.Blog.Tag do
|
defmodule AshHq.Blog.Tag do
|
||||||
@moduledoc "A tag that can be applied to a post. Currently uses CSV data layer and therefore is static"
|
@moduledoc "A tag that can be applied to a post. Currently uses CSV data layer and therefore is static"
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Blog,
|
||||||
data_layer: AshCsv.DataLayer
|
data_layer: AshCsv.DataLayer
|
||||||
|
|
||||||
csv do
|
csv do
|
||||||
|
@ -11,6 +12,7 @@ defmodule AshHq.Blog.Tag do
|
||||||
end
|
end
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
|
|
||||||
create :upsert do
|
create :upsert do
|
||||||
|
@ -21,6 +23,7 @@ defmodule AshHq.Blog.Tag do
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
attribute :name, :ci_string do
|
attribute :name, :ci_string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
primary_key? true
|
primary_key? true
|
||||||
constraints casing: :lower
|
constraints casing: :lower
|
||||||
|
@ -28,7 +31,6 @@ defmodule AshHq.Blog.Tag do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Blog
|
|
||||||
define :upsert, args: [:name]
|
define :upsert, args: [:name]
|
||||||
define :read
|
define :read
|
||||||
define :destroy
|
define :destroy
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule AshHq.Calculations.Decrypt do
|
defmodule AshHq.Calculations.Decrypt do
|
||||||
@moduledoc "Decrypts a given value on demand"
|
@moduledoc "Decrypts a given value on demand"
|
||||||
use Ash.Calculation
|
use Ash.Resource.Calculation
|
||||||
|
|
||||||
def calculate(records, opts, _) do
|
def calculate(records, opts, _) do
|
||||||
{:ok,
|
{:ok,
|
||||||
|
@ -19,10 +19,6 @@ defmodule AshHq.Calculations.Decrypt do
|
||||||
end)}
|
end)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def select(_, opts, _) do
|
|
||||||
[opts[:field]]
|
|
||||||
end
|
|
||||||
|
|
||||||
def load(_, opts, _) do
|
def load(_, opts, _) do
|
||||||
[opts[:field]]
|
[opts[:field]]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule AshHq.Discord do
|
defmodule AshHq.Discord do
|
||||||
@moduledoc "Discord api import & interactions"
|
@moduledoc "Discord api import & interactions"
|
||||||
use Ash.Api
|
use Ash.Domain
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
resource AshHq.Discord.Attachment
|
resource AshHq.Discord.Attachment
|
||||||
|
|
|
@ -1,24 +1,27 @@
|
||||||
defmodule AshHq.Discord.Attachment do
|
defmodule AshHq.Discord.Attachment do
|
||||||
@moduledoc "A discord attachment on a message"
|
@moduledoc "A discord attachment on a message"
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
integer_primary_key :id, generated?: false, writable?: true
|
integer_primary_key :id, generated?: false, writable?: true
|
||||||
attribute :filename, :string
|
attribute :filename, :string, public?: true
|
||||||
attribute :size, :integer
|
attribute :size, :integer, public?: true
|
||||||
attribute :url, :string
|
attribute :url, :string, public?: true
|
||||||
attribute :proxy_url, :string
|
attribute :proxy_url, :string, public?: true
|
||||||
attribute :height, :integer
|
attribute :height, :integer, public?: true
|
||||||
attribute :width, :integer
|
attribute :width, :integer, public?: true
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :message, AshHq.Discord.Message do
|
belongs_to :message, AshHq.Discord.Message do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,11 @@ defmodule AshHq.Discord.Channel do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
|
|
||||||
create :upsert do
|
create :upsert do
|
||||||
|
@ -18,16 +20,20 @@ defmodule AshHq.Discord.Channel do
|
||||||
integer_primary_key :id, writable?: true, generated?: false
|
integer_primary_key :id, writable?: true, generated?: false
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :threads, AshHq.Discord.Thread
|
has_many :threads, AshHq.Discord.Thread do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -36,7 +42,6 @@ defmodule AshHq.Discord.Channel do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Discord
|
|
||||||
define :read
|
define :read
|
||||||
define :upsert
|
define :upsert
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,7 @@ defmodule AshHq.Discord.Message do
|
||||||
Discord messages synchronized by the discord bot
|
Discord messages synchronized by the discord bot
|
||||||
"""
|
"""
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [
|
extensions: [
|
||||||
AshHq.Docs.Extensions.RenderMarkdown,
|
AshHq.Docs.Extensions.RenderMarkdown,
|
||||||
|
@ -10,6 +11,8 @@ defmodule AshHq.Discord.Message do
|
||||||
]
|
]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
|
|
||||||
defaults [:read, :destroy]
|
defaults [:read, :destroy]
|
||||||
|
|
||||||
create :create do
|
create :create do
|
||||||
|
@ -25,6 +28,7 @@ defmodule AshHq.Discord.Message do
|
||||||
end
|
end
|
||||||
|
|
||||||
update :update do
|
update :update do
|
||||||
|
require_atomic? false
|
||||||
primary? true
|
primary? true
|
||||||
argument :attachments, {:array, :map}
|
argument :attachments, {:array, :map}
|
||||||
argument :reactions, {:array, :map}
|
argument :reactions, {:array, :map}
|
||||||
|
@ -59,25 +63,37 @@ defmodule AshHq.Discord.Message do
|
||||||
integer_primary_key :id, generated?: false, writable?: true
|
integer_primary_key :id, generated?: false, writable?: true
|
||||||
|
|
||||||
attribute :author, :string do
|
attribute :author, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :content, :string
|
attribute :content, :string do
|
||||||
attribute :content_html, :string
|
public? true
|
||||||
|
end
|
||||||
|
attribute :content_html, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :timestamp, :utc_datetime do
|
attribute :timestamp, :utc_datetime do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :thread, AshHq.Discord.Thread do
|
belongs_to :thread, AshHq.Discord.Thread do
|
||||||
|
public? true
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
has_many :attachments, AshHq.Discord.Attachment
|
has_many :attachments, AshHq.Discord.Attachment do
|
||||||
has_many :reactions, AshHq.Discord.Reaction
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
|
has_many :reactions, AshHq.Discord.Reaction do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
|
|
@ -3,9 +3,11 @@ defmodule AshHq.Discord.Reaction do
|
||||||
Reactions store emoji reaction counts.
|
Reactions store emoji reaction counts.
|
||||||
"""
|
"""
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -13,16 +15,19 @@ defmodule AshHq.Discord.Reaction do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :count, :integer do
|
attribute :count, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :emoji, :string do
|
attribute :emoji, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :message, AshHq.Discord.Message do
|
belongs_to :message, AshHq.Discord.Message do
|
||||||
|
public? true
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule AshHq.Discord.Tag do
|
defmodule AshHq.Discord.Tag do
|
||||||
@moduledoc "A tag that can be applied to a post. Currently uses CSV data layer and therefore is static"
|
@moduledoc "A tag that can be applied to a post. Currently uses CSV data layer and therefore is static"
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
|
|
||||||
create :upsert do
|
create :upsert do
|
||||||
|
@ -16,14 +18,15 @@ defmodule AshHq.Discord.Tag do
|
||||||
integer_primary_key :id, generated?: false, writable?: true
|
integer_primary_key :id, generated?: false, writable?: true
|
||||||
|
|
||||||
attribute :name, :ci_string do
|
attribute :name, :ci_string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :channel, AshHq.Discord.Channel do
|
belongs_to :channel, AshHq.Discord.Channel do
|
||||||
|
public? true
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
attribute_writable? true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -33,7 +36,6 @@ defmodule AshHq.Discord.Tag do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Discord
|
|
||||||
define :upsert, args: [:channel_id, :id, :name]
|
define :upsert, args: [:channel_id, :id, :name]
|
||||||
define :read
|
define :read
|
||||||
define :destroy
|
define :destroy
|
||||||
|
|
|
@ -4,11 +4,13 @@ defmodule AshHq.Discord.Thread do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
|
|
||||||
read :feed do
|
read :feed do
|
||||||
|
@ -64,31 +66,39 @@ defmodule AshHq.Discord.Thread do
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
integer_primary_key :id, generated?: false, writable?: true
|
integer_primary_key :id, generated?: false, writable?: true
|
||||||
attribute :type, :integer
|
attribute :type, :integer do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :author, :string do
|
attribute :author, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :create_timestamp, :utc_datetime do
|
attribute :create_timestamp, :utc_datetime do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :messages, AshHq.Discord.Message
|
has_many :messages, AshHq.Discord.Message do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
belongs_to :channel, AshHq.Discord.Channel do
|
belongs_to :channel, AshHq.Discord.Channel do
|
||||||
|
public? true
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
attribute_writable? true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
many_to_many :tags, AshHq.Discord.Tag do
|
many_to_many :tags, AshHq.Discord.Tag do
|
||||||
|
public? true
|
||||||
through AshHq.Discord.ThreadTag
|
through AshHq.Discord.ThreadTag
|
||||||
source_attribute_on_join_resource :thread_id
|
source_attribute_on_join_resource :thread_id
|
||||||
destination_attribute_on_join_resource :tag_id
|
destination_attribute_on_join_resource :tag_id
|
||||||
|
@ -101,7 +111,6 @@ defmodule AshHq.Discord.Thread do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Discord
|
|
||||||
define :upsert
|
define :upsert
|
||||||
define :by_id, action: :read, get_by: [:id]
|
define :by_id, action: :read, get_by: [:id]
|
||||||
define :feed, args: [:channel]
|
define :feed, args: [:channel]
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule AshHq.Discord.ThreadTag do
|
defmodule AshHq.Discord.ThreadTag do
|
||||||
@moduledoc "Joins a thread to a tag"
|
@moduledoc "Joins a thread to a tag"
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Discord,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:read, :destroy]
|
defaults [:read, :destroy]
|
||||||
|
|
||||||
create :tag do
|
create :tag do
|
||||||
|
@ -13,16 +15,16 @@ defmodule AshHq.Discord.ThreadTag do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :thread, AshHq.Discord.Thread do
|
belongs_to :thread, AshHq.Discord.Thread do
|
||||||
|
public? true
|
||||||
primary_key? true
|
primary_key? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
attribute_writable? true
|
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :tag, AshHq.Discord.Tag do
|
belongs_to :tag, AshHq.Discord.Tag do
|
||||||
|
public? true
|
||||||
primary_key? true
|
primary_key? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
attribute_writable? true
|
|
||||||
attribute_type :integer
|
attribute_type :integer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -33,7 +35,6 @@ defmodule AshHq.Discord.ThreadTag do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Discord
|
|
||||||
define :tag, args: [:thread_id, :tag_id]
|
define :tag, args: [:thread_id, :tag_id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,12 @@ defmodule AshHq.Docs do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Handles documentation data.
|
Handles documentation data.
|
||||||
"""
|
"""
|
||||||
use Ash.Api,
|
use Ash.Domain,
|
||||||
extensions: [
|
extensions: [
|
||||||
AshGraphql.Api,
|
AshGraphql.Domain,
|
||||||
AshAdmin.Api
|
AshAdmin.Domain
|
||||||
]
|
]
|
||||||
|
|
||||||
use AshHq.ApiHelpers
|
|
||||||
|
|
||||||
admin do
|
admin do
|
||||||
show? true
|
show? true
|
||||||
default_resource_page :primary_read
|
default_resource_page :primary_read
|
||||||
|
@ -20,6 +18,14 @@ defmodule AshHq.Docs do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
registry AshHq.Docs.Registry
|
resource AshHq.Docs.Dsl
|
||||||
|
resource AshHq.Docs.Extension
|
||||||
|
resource AshHq.Docs.Function
|
||||||
|
resource AshHq.Docs.Guide
|
||||||
|
resource AshHq.Docs.Library
|
||||||
|
resource AshHq.Docs.LibraryVersion
|
||||||
|
resource AshHq.Docs.MixTask
|
||||||
|
resource AshHq.Docs.Module
|
||||||
|
resource AshHq.Docs.Option
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
|
||||||
Ash.Changeset.get_attribute(changeset, :name)
|
Ash.Changeset.get_attribute(changeset, :name)
|
||||||
|
|
||||||
changeset.resource == AshHq.Docs.Function ->
|
changeset.resource == AshHq.Docs.Function ->
|
||||||
AshHq.Docs.get!(
|
Ash.get!(
|
||||||
AshHq.Docs.Module,
|
AshHq.Docs.Module,
|
||||||
Ash.Changeset.get_attribute(changeset, :module_id)
|
Ash.Changeset.get_attribute(changeset, :module_id)
|
||||||
).name
|
).name
|
||||||
|
@ -49,7 +49,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
|
||||||
AshHq.Docs.Library
|
AshHq.Docs.Library
|
||||||
|> Ash.Query.select(:name)
|
|> Ash.Query.select(:name)
|
||||||
|> Ash.Query.filter(versions.id == ^library_version_id)
|
|> Ash.Query.filter(versions.id == ^library_version_id)
|
||||||
|> AshHq.Docs.read_one!()
|
|> Ash.read_one!()
|
||||||
|> Map.get(:name)
|
|> Map.get(:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@ defmodule AshHq.Docs.Extensions.Search.Transformers.AddSearchStructure do
|
||||||
Ash.Resource.Dsl,
|
Ash.Resource.Dsl,
|
||||||
[:attributes],
|
[:attributes],
|
||||||
:attribute,
|
:attribute,
|
||||||
private?: true,
|
|
||||||
name: config.sanitized_name_attribute,
|
name: config.sanitized_name_attribute,
|
||||||
type: :string,
|
type: :string,
|
||||||
allow_nil?: false
|
allow_nil?: false
|
||||||
|
|
|
@ -3,8 +3,8 @@ defmodule AshHq.Docs.Extensions.Search.Types do
|
||||||
A static list of all search types that currently exist
|
A static list of all search types that currently exist
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@search_types [AshHq.Docs.Registry]
|
@search_types [AshHq.Docs]
|
||||||
|> Enum.flat_map(&Ash.Registry.Info.entries/1)
|
|> Enum.flat_map(&Ash.Domain.Info.resources/1)
|
||||||
|> Enum.filter(&(AshHq.Docs.Extensions.Search in Spark.extensions(&1)))
|
|> Enum.filter(&(AshHq.Docs.Extensions.Search in Spark.extensions(&1)))
|
||||||
|> Enum.map(&AshHq.Docs.Extensions.Search.type/1)
|
|> Enum.map(&AshHq.Docs.Extensions.Search.type/1)
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|
|
|
@ -73,7 +73,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
resource
|
resource
|
||||||
|> Ash.Query.filter(id in ^ids)
|
|> Ash.Query.filter(id in ^ids)
|
||||||
|> Ash.Query.load(AshHq.Docs.Extensions.Search.load_for_search(resource))
|
|> Ash.Query.load(AshHq.Docs.Extensions.Search.load_for_search(resource))
|
||||||
|> AshHq.Docs.read!()
|
|> Ash.read!()
|
||||||
|> Enum.map(fn item ->
|
|> Enum.map(fn item ->
|
||||||
Ash.Resource.put_metadata(item, :search_score, scores[item.id])
|
Ash.Resource.put_metadata(item, :search_score, scores[item.id])
|
||||||
end)
|
end)
|
||||||
|
@ -125,7 +125,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp dsls do
|
defp dsls do
|
||||||
AshHq.Docs.Dsl
|
AshHq.Docs.Dsl
|
||||||
|> Ash.Query.load([:library_name, :extension_module])
|
|> Ash.Query.load([:library_name, :extension_module])
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn dsl ->
|
|> Stream.map(fn dsl ->
|
||||||
%{
|
%{
|
||||||
"id" => id("dsl", dsl.id),
|
"id" => id("dsl", dsl.id),
|
||||||
|
@ -140,7 +140,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp guides do
|
defp guides do
|
||||||
AshHq.Docs.Guide
|
AshHq.Docs.Guide
|
||||||
|> Ash.Query.load(library_version: :library)
|
|> Ash.Query.load(library_version: :library)
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn guide ->
|
|> Stream.map(fn guide ->
|
||||||
%{
|
%{
|
||||||
"id" => id("guide", guide.id),
|
"id" => id("guide", guide.id),
|
||||||
|
@ -154,7 +154,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp options do
|
defp options do
|
||||||
AshHq.Docs.Option
|
AshHq.Docs.Option
|
||||||
|> Ash.Query.load([:library_name, :extension_module])
|
|> Ash.Query.load([:library_name, :extension_module])
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn option ->
|
|> Stream.map(fn option ->
|
||||||
%{
|
%{
|
||||||
"id" => id("option", option.id),
|
"id" => id("option", option.id),
|
||||||
|
@ -169,7 +169,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp modules do
|
defp modules do
|
||||||
AshHq.Docs.Module
|
AshHq.Docs.Module
|
||||||
|> Ash.Query.load([:library_name])
|
|> Ash.Query.load([:library_name])
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn module ->
|
|> Stream.map(fn module ->
|
||||||
%{
|
%{
|
||||||
"id" => id("module", module.id),
|
"id" => id("module", module.id),
|
||||||
|
@ -184,7 +184,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp mix_tasks do
|
defp mix_tasks do
|
||||||
AshHq.Docs.MixTask
|
AshHq.Docs.MixTask
|
||||||
|> Ash.Query.load([:library_name])
|
|> Ash.Query.load([:library_name])
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn mix_task ->
|
|> Stream.map(fn mix_task ->
|
||||||
%{
|
%{
|
||||||
"id" => id("mix_task", mix_task.id),
|
"id" => id("mix_task", mix_task.id),
|
||||||
|
@ -199,7 +199,7 @@ defmodule AshHq.Docs.Indexer do
|
||||||
defp functions do
|
defp functions do
|
||||||
AshHq.Docs.Function
|
AshHq.Docs.Function
|
||||||
|> Ash.Query.load([:library_name, :call_name])
|
|> Ash.Query.load([:library_name, :call_name])
|
||||||
|> AshHq.Docs.stream!()
|
|> Ash.stream!()
|
||||||
|> Stream.map(fn function ->
|
|> Stream.map(fn function ->
|
||||||
%{
|
%{
|
||||||
"id" => id("function", function.id),
|
"id" => id("function", function.id),
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
defmodule AshHq.Docs.Registry do
|
|
||||||
@moduledoc false
|
|
||||||
use Ash.Registry,
|
|
||||||
extensions: [Ash.Registry.ResourceValidations]
|
|
||||||
|
|
||||||
entries do
|
|
||||||
entry AshHq.Docs.Dsl
|
|
||||||
entry AshHq.Docs.Extension
|
|
||||||
entry AshHq.Docs.Function
|
|
||||||
entry AshHq.Docs.Guide
|
|
||||||
entry AshHq.Docs.Library
|
|
||||||
entry AshHq.Docs.LibraryVersion
|
|
||||||
entry AshHq.Docs.MixTask
|
|
||||||
entry AshHq.Docs.Module
|
|
||||||
entry AshHq.Docs.Option
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.Dsl do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -57,39 +59,61 @@ defmodule AshHq.Docs.Dsl do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :requires_extension, :string
|
attribute :requires_extension, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :doc, :string do
|
attribute :doc, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc_html, :string do
|
attribute :doc_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :imports, {:array, :string} do
|
attribute :imports, {:array, :string} do
|
||||||
|
public? true
|
||||||
default []
|
default []
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :examples, {:array, :string}
|
attribute :examples, {:array, :string} do
|
||||||
attribute :args, {:array, :string}
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
|
attribute :args, {:array, :string} do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :optional_args, {:array, :string} do
|
attribute :optional_args, {:array, :string} do
|
||||||
|
public? true
|
||||||
default []
|
default []
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :arg_defaults, :map
|
attribute :arg_defaults, :map do
|
||||||
attribute :path, {:array, :string}
|
public? true
|
||||||
attribute :recursive_as, :string
|
end
|
||||||
attribute :order, :integer, allow_nil?: false
|
attribute :path, {:array, :string} do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
attribute :recursive_as, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
|
allow_nil? false
|
||||||
|
end
|
||||||
|
|
||||||
attribute :type, :atom do
|
attribute :type, :atom do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints one_of: [:entity, :section]
|
constraints one_of: [:entity, :section]
|
||||||
end
|
end
|
||||||
|
@ -99,16 +123,24 @@ defmodule AshHq.Docs.Dsl do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :extension, AshHq.Docs.Extension do
|
belongs_to :extension, AshHq.Docs.Extension do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :dsl, __MODULE__
|
belongs_to :dsl, __MODULE__ do
|
||||||
has_many :options, AshHq.Docs.Option
|
public? true
|
||||||
has_many :dsls, __MODULE__
|
end
|
||||||
|
has_many :options, AshHq.Docs.Option do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
has_many :dsls, __MODULE__ do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -124,7 +156,6 @@ defmodule AshHq.Docs.Dsl do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Docs
|
|
||||||
define :read
|
define :read
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,11 @@ defmodule AshHq.Docs.Extension do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -33,18 +35,25 @@ defmodule AshHq.Docs.Extension do
|
||||||
attributes do
|
attributes do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :module, :string
|
attribute :module, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
has_many :dsls, AshHq.Docs.Dsl
|
has_many :dsls, AshHq.Docs.Dsl do
|
||||||
has_many :options, AshHq.Docs.Option
|
public? true
|
||||||
|
end
|
||||||
|
has_many :options, AshHq.Docs.Option do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -57,7 +66,6 @@ defmodule AshHq.Docs.Extension do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Docs
|
|
||||||
|
|
||||||
define :destroy
|
define :destroy
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.Function do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -51,45 +53,58 @@ defmodule AshHq.Docs.Function do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :file, :string
|
attribute :file, :string do
|
||||||
attribute :line, :integer
|
public? true
|
||||||
|
end
|
||||||
|
attribute :line, :integer do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :arity, :integer do
|
attribute :arity, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :type, :atom do
|
attribute :type, :atom do
|
||||||
|
public? true
|
||||||
constraints one_of: [:function, :macro, :callback, :type]
|
constraints one_of: [:function, :macro, :callback, :type]
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :heads, {:array, :string} do
|
attribute :heads, {:array, :string} do
|
||||||
|
public? true
|
||||||
default []
|
default []
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :heads_html, {:array, :string} do
|
attribute :heads_html, {:array, :string} do
|
||||||
|
public? true
|
||||||
default []
|
default []
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc, :string do
|
attribute :doc, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc_html, :string do
|
attribute :doc_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :deprecated, :string do
|
attribute :deprecated, :string do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,10 +113,12 @@ defmodule AshHq.Docs.Function do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :module, AshHq.Docs.Module do
|
belongs_to :module, AshHq.Docs.Module do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -115,9 +132,6 @@ defmodule AshHq.Docs.Function do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Docs
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description "A function in a module exposed by an Ash library"
|
description "A function in a module exposed by an Ash library"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule AshHq.Docs.Guide do
|
defmodule AshHq.Docs.Guide do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [
|
extensions: [
|
||||||
AshHq.Docs.Extensions.Search,
|
AshHq.Docs.Extensions.Search,
|
||||||
|
@ -10,6 +11,7 @@ defmodule AshHq.Docs.Guide do
|
||||||
]
|
]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :update, :destroy]
|
defaults [:create, :update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -66,39 +68,47 @@ defmodule AshHq.Docs.Guide do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :text, :string do
|
attribute :text, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :text_html, :string do
|
attribute :text_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :category, :string do
|
attribute :category, :string do
|
||||||
|
public? true
|
||||||
default "Topics"
|
default "Topics"
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :route, :string do
|
attribute :route, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :sanitized_route, :string do
|
attribute :sanitized_route, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :default, :boolean do
|
attribute :default, :boolean do
|
||||||
|
public? true
|
||||||
default false
|
default false
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
@ -121,9 +131,6 @@ defmodule AshHq.Docs.Guide do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Docs
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description "Represents a markdown guide exposed by a library"
|
description "Represents a markdown guide exposed by a library"
|
||||||
|
|
|
@ -75,7 +75,7 @@ defmodule AshHq.Docs.Library.Actions.Import do
|
||||||
|
|
||||||
Logger.info("Starting import of #{name}: #{version}")
|
Logger.info("Starting import of #{name}: #{version}")
|
||||||
|
|
||||||
if AshHq.Docs.exists?(
|
if Ash.exists?(
|
||||||
Ash.Query.for_read(AshHq.Docs.LibraryVersion, :read)
|
Ash.Query.for_read(AshHq.Docs.LibraryVersion, :read)
|
||||||
|> Ash.Query.filter(library_id == ^library.id and version == ^version)
|
|> Ash.Query.filter(library_id == ^library.id and version == ^version)
|
||||||
) do
|
) do
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
defmodule AshHq.Docs.Library do
|
defmodule AshHq.Docs.Library do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshOban]
|
extensions: [AshOban]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :update, :destroy]
|
defaults [:create, :update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -31,6 +33,7 @@ defmodule AshHq.Docs.Library do
|
||||||
end
|
end
|
||||||
|
|
||||||
update :import do
|
update :import do
|
||||||
|
require_atomic? false
|
||||||
transaction? false
|
transaction? false
|
||||||
|
|
||||||
argument :metadata, :map do
|
argument :metadata, :map do
|
||||||
|
@ -49,7 +52,7 @@ defmodule AshHq.Docs.Library do
|
||||||
end
|
end
|
||||||
|
|
||||||
oban do
|
oban do
|
||||||
api AshHq.Docs
|
domain AshHq.Docs
|
||||||
|
|
||||||
triggers do
|
triggers do
|
||||||
trigger :import do
|
trigger :import do
|
||||||
|
@ -69,32 +72,42 @@ defmodule AshHq.Docs.Library do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :display_name, :string do
|
attribute :display_name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :description, :string
|
attribute :description, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :repo_org, :string do
|
attribute :repo_org, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
default "ash-project"
|
default "ash-project"
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :module_prefixes, {:array, :string} do
|
attribute :module_prefixes, {:array, :string} do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
default []
|
default []
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :mix_project, :string
|
attribute :mix_project, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :skip_versions, {:array, :string} do
|
attribute :skip_versions, {:array, :string} do
|
||||||
|
public? true
|
||||||
default []
|
default []
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
@ -103,9 +116,12 @@ defmodule AshHq.Docs.Library do
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :versions, AshHq.Docs.LibraryVersion
|
has_many :versions, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
has_one :latest_library_version, AshHq.Docs.LibraryVersion do
|
has_one :latest_library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
sort version: :desc
|
sort version: :desc
|
||||||
from_many? true
|
from_many? true
|
||||||
end
|
end
|
||||||
|
@ -119,8 +135,6 @@ defmodule AshHq.Docs.Library do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Docs
|
|
||||||
|
|
||||||
define :read
|
define :read
|
||||||
define :by_name, args: [:name], get?: true
|
define :by_name, args: [:name], get?: true
|
||||||
define :create
|
define :create
|
||||||
|
|
|
@ -5,10 +5,10 @@ defmodule AshHq.Docs.Library.Preparations.FilterPendingImport do
|
||||||
query
|
query
|
||||||
|> Ash.Query.ensure_selected([:name])
|
|> Ash.Query.ensure_selected([:name])
|
||||||
|> Ash.Query.load(:latest_version)
|
|> Ash.Query.load(:latest_version)
|
||||||
|> Ash.Query.after_action(fn query, results ->
|
|> Ash.Query.after_action(fn _query, results ->
|
||||||
pending_import =
|
pending_import =
|
||||||
results
|
results
|
||||||
|> query.api.load!(:latest_version)
|
|> Ash.load!(:latest_version)
|
||||||
|> Enum.flat_map(fn result ->
|
|> Enum.flat_map(fn result ->
|
||||||
hex_info =
|
hex_info =
|
||||||
Finch.build(:get, "https://hex.pm/api/packages/#{result.name}")
|
Finch.build(:get, "https://hex.pm/api/packages/#{result.name}")
|
||||||
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.LibraryVersion do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -90,10 +92,12 @@ defmodule AshHq.Docs.LibraryVersion do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :version, :string do
|
attribute :version, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :hydrated, :boolean do
|
attribute :hydrated, :boolean do
|
||||||
|
public? true
|
||||||
default false
|
default false
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
@ -103,13 +107,22 @@ defmodule AshHq.Docs.LibraryVersion do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library, AshHq.Docs.Library do
|
belongs_to :library, AshHq.Docs.Library do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
has_many :extensions, AshHq.Docs.Extension
|
has_many :extensions, AshHq.Docs.Extension do
|
||||||
has_many :guides, AshHq.Docs.Guide
|
public? true
|
||||||
has_many :modules, AshHq.Docs.Module
|
end
|
||||||
has_many :mix_tasks, AshHq.Docs.MixTask
|
has_many :guides, AshHq.Docs.Guide do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
has_many :modules, AshHq.Docs.Module do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
has_many :mix_tasks, AshHq.Docs.MixTask do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -118,7 +131,6 @@ defmodule AshHq.Docs.LibraryVersion do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Docs
|
|
||||||
define :build, args: [:library, :version]
|
define :build, args: [:library, :version]
|
||||||
define :defined_for, args: [:library, :versions]
|
define :defined_for, args: [:library, :versions]
|
||||||
define :by_version, args: [:library, :version]
|
define :by_version, args: [:library, :version]
|
||||||
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.MixTask do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -48,30 +50,39 @@ defmodule AshHq.Docs.MixTask do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :category, :string do
|
attribute :category, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
default "Misc"
|
default "Misc"
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :file, :string
|
attribute :file, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :module_name, :string
|
attribute :module_name, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :doc, :string do
|
attribute :doc, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc_html, :string do
|
attribute :doc_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -80,6 +91,7 @@ defmodule AshHq.Docs.MixTask do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -93,9 +105,6 @@ defmodule AshHq.Docs.MixTask do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Docs
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description "Represents a mix task that has been exposed by a library"
|
description "Represents a mix task that has been exposed by a library"
|
||||||
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.Module do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -51,28 +53,35 @@ defmodule AshHq.Docs.Module do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :category, :string do
|
attribute :category, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
default "Misc"
|
default "Misc"
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :file, :string
|
attribute :file, :string do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :doc, :string do
|
attribute :doc, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc_html, :string do
|
attribute :doc_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :order, :integer do
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -81,10 +90,13 @@ defmodule AshHq.Docs.Module do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
has_many :functions, AshHq.Docs.Function
|
has_many :functions, AshHq.Docs.Function do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -96,9 +108,6 @@ defmodule AshHq.Docs.Module do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
|
||||||
define_for AshHq.Docs
|
|
||||||
end
|
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
description "Represents a module that has been exposed by a library"
|
description "Represents a module that has been exposed by a library"
|
||||||
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.Docs.Option do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Docs,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:update, :destroy]
|
defaults [:update, :destroy]
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
|
@ -53,52 +55,70 @@ defmodule AshHq.Docs.Option do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :name, :string do
|
attribute :name, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :type, :string do
|
attribute :type, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc, :string do
|
attribute :doc, :string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
default ""
|
default ""
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :doc_html, :string do
|
attribute :doc_html, :string do
|
||||||
|
public? true
|
||||||
constraints trim?: false, allow_empty?: true
|
constraints trim?: false, allow_empty?: true
|
||||||
writable? false
|
writable? false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :required, :boolean do
|
attribute :required, :boolean do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
default false
|
default false
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :argument_index, :integer
|
attribute :argument_index, :integer do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :links, :map do
|
attribute :links, :map do
|
||||||
|
public? true
|
||||||
default %{}
|
default %{}
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :default, :string
|
attribute :default, :string do
|
||||||
attribute :path, {:array, :string}
|
public? true
|
||||||
attribute :order, :integer, allow_nil?: false
|
end
|
||||||
|
attribute :path, {:array, :string} do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
attribute :order, :integer do
|
||||||
|
public? true
|
||||||
|
allow_nil? false
|
||||||
|
end
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :dsl, AshHq.Docs.Dsl do
|
belongs_to :dsl, AshHq.Docs.Dsl do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
belongs_to :library_version, AshHq.Docs.LibraryVersion do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :extension, AshHq.Docs.Extension do
|
belongs_to :extension, AshHq.Docs.Extension do
|
||||||
|
public? true
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -114,7 +134,6 @@ defmodule AshHq.Docs.Option do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Docs
|
|
||||||
define :read
|
define :read
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@ defmodule AshHq.Github.Contributor.Actions.Import do
|
||||||
|
|
||||||
def run(_input, _, _) do
|
def run(_input, _, _) do
|
||||||
AshHq.Docs.Library
|
AshHq.Docs.Library
|
||||||
|> AshHq.Docs.read!()
|
|> Ash.stream!()
|
||||||
|> Stream.flat_map(fn library ->
|
|> Stream.flat_map(fn library ->
|
||||||
:timer.sleep(1000)
|
|
||||||
opts = []
|
opts = []
|
||||||
|
|
||||||
opts =
|
opts =
|
||||||
|
@ -33,7 +32,7 @@ defmodule AshHq.Github.Contributor.Actions.Import do
|
||||||
Map.put(contributor, "order", index)
|
Map.put(contributor, "order", index)
|
||||||
end)
|
end)
|
||||||
|> Stream.uniq_by(&Map.get(&1, "id"))
|
|> Stream.uniq_by(&Map.get(&1, "id"))
|
||||||
|> AshHq.Github.bulk_create(AshHq.Github.Contributor, :create,
|
|> Ash.bulk_create(AshHq.Github.Contributor, :create,
|
||||||
upsert?: true,
|
upsert?: true,
|
||||||
upsert_fields: [:order, :login, :avatar_url, :html_url],
|
upsert_fields: [:order, :login, :avatar_url, :html_url],
|
||||||
return_errors?: true,
|
return_errors?: true,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
defmodule AshHq.Github.Contributor do
|
defmodule AshHq.Github.Contributor do
|
||||||
@moduledoc "A contributor to any package deployed on Ash HQ."
|
@moduledoc "A contributor to any package deployed on Ash HQ."
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.Github,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
extensions: [AshOban]
|
extensions: [AshOban]
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read, :update, :destroy]
|
defaults [:create, :read, :update, :destroy]
|
||||||
|
|
||||||
read :in_order do
|
read :in_order do
|
||||||
|
@ -19,7 +21,7 @@ defmodule AshHq.Github.Contributor do
|
||||||
end
|
end
|
||||||
|
|
||||||
oban do
|
oban do
|
||||||
api AshHq.Github
|
domain AshHq.Github
|
||||||
|
|
||||||
scheduled_actions do
|
scheduled_actions do
|
||||||
schedule :import, "0 */6 * * *" do
|
schedule :import, "0 */6 * * *" do
|
||||||
|
@ -34,10 +36,10 @@ defmodule AshHq.Github.Contributor do
|
||||||
writable? true
|
writable? true
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :login, :string, allow_nil?: false
|
attribute :login, :string, allow_nil?: false, public?: true
|
||||||
attribute :avatar_url, :string, allow_nil?: false
|
attribute :avatar_url, :string, allow_nil?: false, public?: true
|
||||||
attribute :html_url, :string, allow_nil?: false
|
attribute :html_url, :string, allow_nil?: false, public?: true
|
||||||
attribute :order, :integer, allow_nil?: false
|
attribute :order, :integer, allow_nil?: false, public?: true
|
||||||
end
|
end
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
|
@ -46,7 +48,6 @@ defmodule AshHq.Github.Contributor do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.Github
|
|
||||||
|
|
||||||
define :in_order
|
define :in_order
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule AshHq.Github do
|
defmodule AshHq.Github do
|
||||||
@moduledoc "Api for interacting with data synchronized from github."
|
@moduledoc "Domain for interacting with data synchronized from github."
|
||||||
use Ash.Api
|
use Ash.Domain
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
resource AshHq.Github.Contributor
|
resource AshHq.Github.Contributor
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule AshHq.MailingList.EmailNotifier do
|
defmodule AshHq.MailingList.EmailNotifier do
|
||||||
@moduledoc "Sends emails from events in the MailingList api"
|
@moduledoc "Sends emails from events in the MailingList domain"
|
||||||
use Ash.Notifier
|
use Ash.Notifier
|
||||||
|
|
||||||
def notify(%Ash.Notifier.Notification{
|
def notify(%Ash.Notifier.Notification{
|
||||||
|
|
|
@ -2,9 +2,9 @@ defmodule AshHq.MailingList do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Handles documentation data.
|
Handles documentation data.
|
||||||
"""
|
"""
|
||||||
use Ash.Api, otp_app: :ash_hq
|
use Ash.Domain, otp_app: :ash_hq
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
registry AshHq.MailingList.Registry
|
resource AshHq.MailingList.Email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
defmodule AshHq.MailingList.Registry do
|
|
||||||
@moduledoc false
|
|
||||||
use Ash.Registry,
|
|
||||||
extensions: [Ash.Registry.ResourceValidations]
|
|
||||||
|
|
||||||
entries do
|
|
||||||
entry AshHq.MailingList.Email
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,10 +2,12 @@ defmodule AshHq.MailingList.Email do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: AshHq.MailingList,
|
||||||
data_layer: AshPostgres.DataLayer,
|
data_layer: AshPostgres.DataLayer,
|
||||||
notifiers: AshHq.MailingList.EmailNotifier
|
notifiers: AshHq.MailingList.EmailNotifier
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
|
default_accept :*
|
||||||
defaults [:create, :read]
|
defaults [:create, :read]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -13,6 +15,7 @@ defmodule AshHq.MailingList.Email do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :email, :ci_string do
|
attribute :email, :ci_string do
|
||||||
|
public? true
|
||||||
allow_nil? false
|
allow_nil? false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -25,8 +28,6 @@ defmodule AshHq.MailingList.Email do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshHq.MailingList
|
|
||||||
|
|
||||||
define :all, action: :read
|
define :all, action: :read
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,4 @@ defmodule AshHqWeb.LiveUserAuth do
|
||||||
{:cont, assign(socket, :current_user, nil)}
|
{:cont, assign(socket, :current_user, nil)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_mount(:live_user_required, _params, _session, socket) do
|
|
||||||
if socket.assigns[:current_user] do
|
|
||||||
{:cont, socket}
|
|
||||||
else
|
|
||||||
{:halt, Phoenix.LiveView.redirect(socket, to: ~p"/sign-in")}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -224,7 +224,7 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
|> load_for_search()
|
|> load_for_search()
|
||||||
|
|
||||||
new_libraries =
|
new_libraries =
|
||||||
AshHq.Docs.load!(socket.assigns.libraries, versions: [guides: guides_query])
|
Ash.load!(socket.assigns.libraries, versions: [guides: guides_query])
|
||||||
|
|
||||||
assign(socket, :libraries, new_libraries)
|
assign(socket, :libraries, new_libraries)
|
||||||
end
|
end
|
||||||
|
@ -331,7 +331,7 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
resource
|
resource
|
||||||
|> Ash.Query.select(field)
|
|> Ash.Query.select(field)
|
||||||
|> Ash.Query.filter(id == ^record.id)
|
|> Ash.Query.filter(id == ^record.id)
|
||||||
|> AshHq.Docs.read_one!()
|
|> Ash.read_one!()
|
||||||
|> Map.get(field)
|
|> Map.get(field)
|
||||||
|
|
||||||
Map.put(record, field, value)
|
Map.put(record, field, value)
|
||||||
|
|
|
@ -97,7 +97,7 @@ defmodule AshHqWeb.Pages.Forum do
|
||||||
|> Ash.Query.filter(channel_id == ^socket.assigns.channel.id)
|
|> Ash.Query.filter(channel_id == ^socket.assigns.channel.id)
|
||||||
|> Ash.Query.select(:name)
|
|> Ash.Query.select(:name)
|
||||||
|> Ash.Query.sort(:name)
|
|> Ash.Query.sort(:name)
|
||||||
|> AshHq.Discord.read!()
|
|> Ash.read!()
|
||||||
|> Enum.map(&to_string(&1.name))
|
|> Enum.map(&to_string(&1.name))
|
||||||
|
|
||||||
assign(socket, :tags, tags)
|
assign(socket, :tags, tags)
|
||||||
|
|
|
@ -489,7 +489,6 @@ defmodule AshHqWeb.Pages.Home do
|
||||||
contributors: contributors,
|
contributors: contributors,
|
||||||
email_form:
|
email_form:
|
||||||
AshPhoenix.Form.for_create(AshHq.MailingList.Email, :create,
|
AshPhoenix.Form.for_create(AshHq.MailingList.Email, :create,
|
||||||
api: AshHq.MailingList,
|
|
||||||
upsert?: true,
|
upsert?: true,
|
||||||
upsert_identity: :unique_email
|
upsert_identity: :unique_email
|
||||||
)
|
)
|
||||||
|
@ -638,6 +637,7 @@ defmodule AshHqWeb.Pages.Home do
|
||||||
@post_example """
|
@post_example """
|
||||||
defmodule Example.Post do
|
defmodule Example.Post do
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
|
domain: Example,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
resource do
|
resource do
|
||||||
|
|
|
@ -3,8 +3,7 @@ defmodule AshHqWeb.SessionPlug do
|
||||||
@behaviour Plug
|
@behaviour Plug
|
||||||
|
|
||||||
@cookies_to_replicate [
|
@cookies_to_replicate [
|
||||||
"theme",
|
"theme"
|
||||||
"selected_types"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def init(_), do: []
|
def init(_), do: []
|
||||||
|
|
|
@ -9,7 +9,7 @@ defmodule AshHqWeb.RedirectToHex do
|
||||||
AshHq.Docs.Module
|
AshHq.Docs.Module
|
||||||
|> Ash.Query.filter(name == ^dsl_target or sanitized_name == ^dsl_target)
|
|> Ash.Query.filter(name == ^dsl_target or sanitized_name == ^dsl_target)
|
||||||
|> Ash.Query.load(to_load)
|
|> Ash.Query.load(to_load)
|
||||||
|> AshHq.Docs.read_one()
|
|> Ash.read_one()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, module} when not is_nil(module) ->
|
{:ok, module} when not is_nil(module) ->
|
||||||
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
||||||
|
@ -30,7 +30,7 @@ defmodule AshHqWeb.RedirectToHex do
|
||||||
AshHq.Docs.MixTask
|
AshHq.Docs.MixTask
|
||||||
|> Ash.Query.filter(name == ^mix_task or sanitized_name == ^mix_task)
|
|> Ash.Query.filter(name == ^mix_task or sanitized_name == ^mix_task)
|
||||||
|> Ash.Query.load(to_load)
|
|> Ash.Query.load(to_load)
|
||||||
|> AshHq.Docs.read_one()
|
|> Ash.read_one()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, module} when not is_nil(module) ->
|
{:ok, module} when not is_nil(module) ->
|
||||||
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
||||||
|
@ -51,7 +51,7 @@ defmodule AshHqWeb.RedirectToHex do
|
||||||
AshHq.Docs.Module
|
AshHq.Docs.Module
|
||||||
|> Ash.Query.filter(name == ^module or sanitized_name == ^module)
|
|> Ash.Query.filter(name == ^module or sanitized_name == ^module)
|
||||||
|> Ash.Query.load(to_load)
|
|> Ash.Query.load(to_load)
|
||||||
|> AshHq.Docs.read_one()
|
|> Ash.read_one()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, module} when not is_nil(module) ->
|
{:ok, module} when not is_nil(module) ->
|
||||||
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
||||||
|
@ -67,7 +67,7 @@ defmodule AshHqWeb.RedirectToHex do
|
||||||
AshHq.Docs.Module
|
AshHq.Docs.Module
|
||||||
|> Ash.Query.filter(name == ^module or sanitized_name == ^module)
|
|> Ash.Query.filter(name == ^module or sanitized_name == ^module)
|
||||||
|> Ash.Query.load(to_load)
|
|> Ash.Query.load(to_load)
|
||||||
|> AshHq.Docs.read_one()
|
|> Ash.read_one()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, module} when not is_nil(module) ->
|
{:ok, module} when not is_nil(module) ->
|
||||||
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
{:halt, redirect(socket, external: AshHqWeb.DocRoutes.doc_link(module))}
|
||||||
|
|
|
@ -10,12 +10,10 @@ defmodule AshHqWeb.Router do
|
||||||
plug(:put_root_layout, {AshHqWeb.LayoutView, :root})
|
plug(:put_root_layout, {AshHqWeb.LayoutView, :root})
|
||||||
plug(:protect_from_forgery)
|
plug(:protect_from_forgery)
|
||||||
plug(AshHqWeb.SessionPlug)
|
plug(AshHqWeb.SessionPlug)
|
||||||
plug(:load_from_session)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :api do
|
pipeline :api do
|
||||||
plug(:accepts, ["json"])
|
plug(:accepts, ["json"])
|
||||||
plug(:load_from_bearer)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :admin_basic_auth do
|
pipeline :admin_basic_auth do
|
||||||
|
|
|
@ -2,9 +2,9 @@ defmodule AshHqWeb.Schema do
|
||||||
@moduledoc "The absinthe graphql schema"
|
@moduledoc "The absinthe graphql schema"
|
||||||
use Absinthe.Schema
|
use Absinthe.Schema
|
||||||
|
|
||||||
@apis [AshHq.Docs]
|
@domains [AshHq.Docs]
|
||||||
|
|
||||||
use AshGraphql, apis: @apis
|
use AshGraphql, domains: @domains
|
||||||
|
|
||||||
query do
|
query do
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="<%= "#{@configured_theme}" %>">
|
<html lang="en" class={@configured_theme}>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||||
<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] || "Ash Framework" %>
|
<.live_title>
|
||||||
|
<%= assigns[:page_title] || "Ash Framework" %>
|
||||||
|
</.live_title>
|
||||||
<%= if Application.get_env(:ash_hq, :analytics?) do %>
|
<%= if Application.get_env(:ash_hq, :analytics?) do %>
|
||||||
<script defer data-domain="ash-hq.org" src="https://plausible.io/js/plausible.js"></script>
|
<script defer data-domain="ash-hq.org" src="https://plausible.io/js/plausible.js"></script>
|
||||||
<% end %>
|
<% end %>
|
||||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
|
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.2/jquery.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.2/jquery.min.js"></script>
|
||||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/assets/app.css") %>"/>
|
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
<%= case live_flash(@flash, :info) do %>
|
<%= case live_flash(@flash, :info) do %>
|
||||||
|
@ -34,6 +36,6 @@
|
||||||
<%= if @live_action == :media do %>
|
<%= if @live_action == :media do %>
|
||||||
<script src="https://platform.twitter.com/widgets.js" charset="utf-8" ></script>
|
<script src="https://platform.twitter.com/widgets.js" charset="utf-8" ></script>
|
||||||
<% end %>
|
<% end %>
|
||||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/assets/app.js") %>"></script>
|
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -41,7 +41,6 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
uri={@uri}
|
uri={@uri}
|
||||||
close={close_search()}
|
close={close_search()}
|
||||||
libraries={@libraries}
|
libraries={@libraries}
|
||||||
selected_types={@selected_types}
|
|
||||||
change_types="change-types"
|
change_types="change-types"
|
||||||
change_versions="change-versions"
|
change_versions="change-versions"
|
||||||
remove_version="remove_version"
|
remove_version="remove_version"
|
||||||
|
@ -158,23 +157,6 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("change-types", %{"types" => types}, socket) do
|
|
||||||
types =
|
|
||||||
types
|
|
||||||
|> Enum.filter(fn {_, value} ->
|
|
||||||
value == "true"
|
|
||||||
end)
|
|
||||||
|> Enum.map(&elem(&1, 0))
|
|
||||||
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> assign(
|
|
||||||
:selected_types,
|
|
||||||
types
|
|
||||||
)
|
|
||||||
|> push_event("selected-types", %{types: types})}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("toggle_theme", _, socket) do
|
def handle_event("toggle_theme", _, socket) do
|
||||||
theme =
|
theme =
|
||||||
case socket.assigns.configured_theme do
|
case socket.assigns.configured_theme do
|
||||||
|
@ -206,19 +188,6 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
|
|
||||||
configured_theme = session["theme"] || "system"
|
configured_theme = session["theme"] || "system"
|
||||||
|
|
||||||
all_types = AshHq.Docs.Extensions.Search.Types.types()
|
|
||||||
|
|
||||||
selected_types =
|
|
||||||
case session["selected_types"] do
|
|
||||||
nil ->
|
|
||||||
AshHq.Docs.Extensions.Search.Types.types()
|
|
||||||
|
|
||||||
types ->
|
|
||||||
types
|
|
||||||
|> String.split(",")
|
|
||||||
|> Enum.filter(&(&1 in all_types))
|
|
||||||
end
|
|
||||||
|
|
||||||
versions_query =
|
versions_query =
|
||||||
AshHq.Docs.LibraryVersion
|
AshHq.Docs.LibraryVersion
|
||||||
|> Ash.Query.sort(version: :desc)
|
|> Ash.Query.sort(version: :desc)
|
||||||
|
@ -228,12 +197,7 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(:libraries, libraries)
|
|> assign(:libraries, libraries)
|
||||||
|> assign(
|
|> assign(configured_theme: configured_theme)}
|
||||||
:selected_types,
|
|
||||||
selected_types
|
|
||||||
)
|
|
||||||
|> assign(configured_theme: configured_theme)
|
|
||||||
|> push_event("selected_types", %{types: selected_types})}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def toggle_search(js \\ %JS{}) do
|
def toggle_search(js \\ %JS{}) do
|
||||||
|
|
4
mix.exs
4
mix.exs
|
@ -39,7 +39,8 @@ defmodule AshHq.MixProject do
|
||||||
# Type `mix help deps` for examples and options.
|
# Type `mix help deps` for examples and options.
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:ash, "~> 3.0.0-rc"},
|
# {:ash, "~> 3.0.0-rc"},
|
||||||
|
{:ash, path: "../../ash/ash", override: true},
|
||||||
{:ash_postgres, "~> 2.0.0-rc"},
|
{:ash_postgres, "~> 2.0.0-rc"},
|
||||||
{:ash_admin, "~> 0.10.10-rc"},
|
{:ash_admin, "~> 0.10.10-rc"},
|
||||||
{:ash_phoenix, "~> 2.0.0-rc"},
|
{:ash_phoenix, "~> 2.0.0-rc"},
|
||||||
|
@ -99,6 +100,7 @@ defmodule AshHq.MixProject do
|
||||||
{:phoenix_html, "~> 4.0"},
|
{:phoenix_html, "~> 4.0"},
|
||||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||||
{:phoenix_live_view, "~> 0.18"},
|
{:phoenix_live_view, "~> 0.18"},
|
||||||
|
{:html_entities, "~> 0.5"},
|
||||||
# locked for compatibility
|
# locked for compatibility
|
||||||
{:finch, "~> 0.10"},
|
{:finch, "~> 0.10"},
|
||||||
{:floki, "~> 0.30"},
|
{:floki, "~> 0.30"},
|
||||||
|
|
3
mix.lock
3
mix.lock
|
@ -44,7 +44,7 @@
|
||||||
"equivalex": {:hex, :equivalex, "1.0.3", "170d9a82ae066e0020dfe1cf7811381669565922eb3359f6c91d7e9a1124ff74", [:mix], [], "hexpm", "46fa311adb855117d36e461b9c0ad2598f72110ad17ad73d7533c78020e045fc"},
|
"equivalex": {:hex, :equivalex, "1.0.3", "170d9a82ae066e0020dfe1cf7811381669565922eb3359f6c91d7e9a1124ff74", [:mix], [], "hexpm", "46fa311adb855117d36e461b9c0ad2598f72110ad17ad73d7533c78020e045fc"},
|
||||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||||
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
|
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
|
||||||
"ets": {:hex, :ets, "0.8.1", "8ff9bcda5682b98493f8878fc9dbd990e48d566cba8cce59f7c2a78130da29ea", [:mix], [], "hexpm", "6be41b50adb5bc5c43626f25ea2d0af1f4a242fb3fad8d53f0c67c20b78915cc"},
|
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
|
||||||
"ex_check": {:hex, :ex_check, "0.16.0", "07615bef493c5b8d12d5119de3914274277299c6483989e52b0f6b8358a26b5f", [:mix], [], "hexpm", "4d809b72a18d405514dda4809257d8e665ae7cf37a7aee3be6b74a34dec310f5"},
|
"ex_check": {:hex, :ex_check, "0.16.0", "07615bef493c5b8d12d5119de3914274277299c6483989e52b0f6b8358a26b5f", [:mix], [], "hexpm", "4d809b72a18d405514dda4809257d8e665ae7cf37a7aee3be6b74a34dec310f5"},
|
||||||
"ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"},
|
"ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"},
|
||||||
"excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"},
|
"excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"},
|
||||||
|
@ -61,6 +61,7 @@
|
||||||
"hackney": {:hex, :hackney, "1.17.1", "08463f93d2cc1a03817bf28d8dae6021543f773bd436c9377047224856c4422c", [:rebar3], [{:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~> 3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "d2cba9e3c8103ad0320623e9f1c33e8d378a15eaabe2ee8ae441898f3d35a18c"},
|
"hackney": {:hex, :hackney, "1.17.1", "08463f93d2cc1a03817bf28d8dae6021543f773bd436c9377047224856c4422c", [:rebar3], [{:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~> 3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "d2cba9e3c8103ad0320623e9f1c33e8d378a15eaabe2ee8ae441898f3d35a18c"},
|
||||||
"haystack": {:hex, :haystack, "0.1.0", "6cb9c72caf40ed4a5f9a094e6b09993c68c3fda0e01280c60c331a19860c504c", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:stemmer, "~> 1.1", [hex: :stemmer, repo: "hexpm", optional: false]}], "hexpm", "27a582513ef933c1b11345b96f8d41ee137d03b25312bd85068ffe8fec503635"},
|
"haystack": {:hex, :haystack, "0.1.0", "6cb9c72caf40ed4a5f9a094e6b09993c68c3fda0e01280c60c331a19860c504c", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:stemmer, "~> 1.1", [hex: :stemmer, repo: "hexpm", optional: false]}], "hexpm", "27a582513ef933c1b11345b96f8d41ee137d03b25312bd85068ffe8fec503635"},
|
||||||
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
|
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
|
||||||
|
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
||||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||||
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
||||||
"json_xema": {:hex, :json_xema, "0.4.2", "85de190f597a98ce9da436b8a59c97ef561a6ab6017255df8b494babefd6fb10", [:mix], [{:conv_case, "~> 0.2", [hex: :conv_case, repo: "hexpm", optional: false]}, {:xema, "~> 0.11", [hex: :xema, repo: "hexpm", optional: false]}], "hexpm", "5516213758667d21669e0d63ea287238d277519527bac6c02140a5e34c1fda80"},
|
"json_xema": {:hex, :json_xema, "0.4.2", "85de190f597a98ce9da436b8a59c97ef561a6ab6017255df8b494babefd6fb10", [:mix], [{:conv_case, "~> 0.2", [hex: :conv_case, repo: "hexpm", optional: false]}, {:xema, "~> 0.11", [hex: :xema, repo: "hexpm", optional: false]}], "hexpm", "5516213758667d21669e0d63ea287238d277519527bac6c02140a5e34c1fda80"},
|
||||||
|
|
Loading…
Reference in a new issue