diff --git a/lib/elixir_boilerplate/planning/planning.ex b/lib/elixir_boilerplate/planning/planning.ex new file mode 100644 index 00000000..ed8c4ba2 --- /dev/null +++ b/lib/elixir_boilerplate/planning/planning.ex @@ -0,0 +1,31 @@ +defmodule ElixirBoilerplate.Planning do + alias ElixirBoilerplate.Planning.Project + alias ElixirBoilerplate.Repo + + import Ecto.Query + + def list() do + projects = + queryable() + |> Repo.all() + + {:ok, projects} + end + + def get(project_id) do + project = + queryable() + |> where(id: ^project_id) + |> Repo.one() + + {:ok, project} + end + + defp queryable() do + from(p in Project, + join: t in assoc(p, :tasks), + order_by: [asc: field(t, :priority)], + preload: [tasks: t] + ) + end +end diff --git a/lib/elixir_boilerplate/planning/project.ex b/lib/elixir_boilerplate/planning/project.ex index 9f20a731..b6b3a28f 100644 --- a/lib/elixir_boilerplate/planning/project.ex +++ b/lib/elixir_boilerplate/planning/project.ex @@ -1,12 +1,16 @@ defmodule ElixirBoilerplate.Planning.Project do use ElixirBoilerplate.Schema + alias ElixirBoilerplate.Planning.Task + schema "projects" do field :description, :string - field :launch_at, :naive_datetime - field :next_milestone_at, :naive_datetime + field :launch_at, :utc_datetime + field :next_milestone_at, :utc_datetime field :title, :string + has_many :tasks, Task + timestamps() end diff --git a/lib/elixir_boilerplate_graphql/planning/types.ex b/lib/elixir_boilerplate_graphql/planning/types.ex new file mode 100644 index 00000000..e8d6fa43 --- /dev/null +++ b/lib/elixir_boilerplate_graphql/planning/types.ex @@ -0,0 +1,33 @@ +defmodule ElixirBoilerplateGraphQL.Planning.Types do + use Absinthe.Schema.Notation + + object :project do + @desc "A sample project" + field(:id, :id) + field(:title, :string) + field(:description, :string) + field(:launch_at, :datetime) + field(:tasks, list_of(:task)) + end + + object :task do + @desc "A sample task" + field(:id, :id) + field(:description, :string) + field(:priority, :integer) + field(:due_at, :datetime) + end + + object :planning_queries do + @desc "A list of projects" + field :projects, list_of(:project) do + resolve(fn _parent, _args, _resolution -> ElixirBoilerplate.Planning.list() end) + end + + @desc "A project" + field :project, :project do + arg(:id, :id) + resolve(fn _parent, %{id: id}, _resolution -> ElixirBoilerplate.Planning.get(id) end) + end + end +end diff --git a/lib/elixir_boilerplate_graphql/schema.ex b/lib/elixir_boilerplate_graphql/schema.ex index 97d98723..7a0daceb 100644 --- a/lib/elixir_boilerplate_graphql/schema.ex +++ b/lib/elixir_boilerplate_graphql/schema.ex @@ -3,9 +3,11 @@ defmodule ElixirBoilerplateGraphQL.Schema do import_types(Absinthe.Type.Custom) import_types(ElixirBoilerplateGraphQL.Application.Types) + import_types(ElixirBoilerplateGraphQL.Planning.Types) query do import_fields(:application_queries) + import_fields(:planning_queries) end # Having an empty mutation block is invalid and raises an error in Absinthe. @@ -13,6 +15,7 @@ defmodule ElixirBoilerplateGraphQL.Schema do # # mutation do # import_fields(:application_mutations) + # import_fields(:planning_mutations) # end def context(context) do