defmodule AshHqWeb.Pages.Home do @moduledoc "The home page" use Surface.LiveComponent alias AshHqWeb.Components.{CalloutText, CodeExample, SearchBar} alias Surface.Components.Form alias Surface.Components.Form.{Field, ErrorTag, TextInput, Submit} import AshHqWeb.Components.CodeExample, only: [to_code: 1] data signed_up, :boolean, default: false data email_form, :any def render(assigns) do ~F"""
This site is still under construction and is live for preview purposes only.
Build powerful and composable applications with a flexible tool-chain.
A declarative foundation for ambitious applications. Model your domain, derive the rest.
{#if @signed_up} Thank you for joining our mailing list! {#else}
Join
{/if}

"Through its declarative extensibility, Ash delivers more than you'd expect: Powerful APIs with filtering/sorting/pagination/calculations/aggregations, pub/sub, authorization, rich introspection, GraphQL... It's what empowers this solo developer to build an ambitious ERP!"

Frank Dugan III
System Specialist, SunnyCor Inc.

"What stood out to me was how incredibly easy Ash made it for me to go from a proof of concept, to a working prototype using ETS, to a live app using Postgres."

Brett Kolodny
Full stack engineer, MEW

"Ash is such powerful idea and it gives Alembic such a massive competitive advantage that I’d be really stupid to tell anyone about it."

Josh Price
Technical Director, Alembic

{#if @signed_up} Thank you for joining our mailing list! {#else}

Join our mailing list for (tastefully paced) updates!

Join
{/if}
Why do we keep reinventing the wheel?
{#if @signed_up} Thank you for joining our mailing list! {#else}

Join our mailing list for (tastefully paced) updates!

Join
{/if}
""" end def mount(socket) do {:ok, assign( socket, signed_up: false, email_form: AshPhoenix.Form.for_create(AshHq.MailingList.Email, :create, api: AshHq.MailingList, upsert?: true, upsert_identity: :unique_email ) )} end def handle_event("validate_email_form", %{"form" => form}, socket) do {:noreply, assign(socket, email_form: AshPhoenix.Form.validate(socket.assigns.email_form, form))} end def handle_event("submit_email_form", _, socket) do case AshPhoenix.Form.submit(socket.assigns.email_form) do {:ok, _} -> {:noreply, assign(socket, :signed_up, true)} {:error, form} -> {:noreply, assign(socket, email_form: form)} end end @changeset_example """ post = Example.Post.create!(%{ text: "Declarative programming is fun!" }) Example.Post.react!(post, %{type: :like}) Example.Post |> Ash.Query.filter(likes > 10) |> Ash.Query.sort(likes: :desc) |> Example.read!() """ |> to_code() defp changeset_example do @changeset_example end @live_view_example """ def mount(_params, _session, socket) do form = AshPhoenix.Form.for_create(Example.Post, :create) {:ok, assign(socket, :form, form}} end def handle_event("validate", %{"form" => input}, socket) do form = AshPhoenix.Form.validate(socket.assigns.form, input) {:ok, assign(socket, :form, form)} end def handle_event("submit", _, socket) do case AshPhoenix.Form.submit(socket.assigns.form) do {:ok, post} -> {:ok, redirect_to_post(socket, post)} {:error, form_with_errors} -> {:noreply, assign(socket, :form, form_with_errors)} end end """ |> to_code() defp live_view_example do @live_view_example end @graphql_example """ graphql do type :post queries do get :get_post, :read list :feed, :read end mutations do create :create_post, :create update :react_to_post, :react end end """ |> to_code() defp graphql_example do @graphql_example end @policies_example """ policies do policy action_type(:read) do authorize_if expr(visibility == :everyone) authorize_if relates_to_actor_via([:author, :friends]) end end """ |> to_code() defp policies_example do @policies_example end @notifier_example """ pub_sub do module ExampleEndpoint prefix "post" publish_all :create, ["created"] publish :react, ["reaction", :id] event: "reaction" end """ |> to_code() defp notifier_example do @notifier_example end @aggregate_example """ aggregates do count :likes, :reactions do filter expr(type == :like) end count :dislikes, :reactions do filter expr(type == :dislike) end end calculations do calculate :like_ratio, :float do expr(likes / (likes + dislikes)) end end """ |> to_code() defp aggregate_example do @aggregate_example end @post_example """ defmodule Example.Post do use AshHq.Resource, data_layer: AshPostgres.DataLayer postgres do table "posts" repo Example.Repo end attributes do attribute :text, :string do allow_nil? false end attribute :visibility, :atom do constraints [ one_of: [:friends, :everyone] ] end end actions do update :react do argument :type, Example.Types.ReactionType do allow_nil? false end change manage_relationship( :type, :reactions, type: :append ) end end relationships do belongs_to :author, Example.User do required? true end has_many :reactions, Example.Reaction end end """ |> to_code() defp post_example do @post_example end end