Skip to content

Commit

Permalink
Added minimal support system (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
vloothuis authored Aug 27, 2021
1 parent 8f42519 commit 26934e2
Show file tree
Hide file tree
Showing 25 changed files with 540 additions and 5 deletions.
8 changes: 6 additions & 2 deletions core/bundles/link/lib/layouts/workspace/menu_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ defmodule Link.Layouts.Workspace.MenuBuilder do

[]
|> append(live_item(socket, :dashboard, active_item), can_access?(user_state, Link.Dashboard))
|> append(live_item(socket, :surveys, active_item), can_access?(user_state, CoreWeb.Study.New))
|> append(
live_item(socket, :surveys, active_item),
can_access?(user_state, CoreWeb.Study.New)
)
|> append(live_item(socket, :studentpool, active_item), user_state.coordinator)
|> append(live_item(socket, :marketplace, active_item))
|> append(live_item(socket, :todo, active_item, true, next_action_count))
Expand All @@ -48,9 +51,10 @@ defmodule Link.Layouts.Workspace.MenuBuilder do
defp build_menu_second_part(socket, active_item, page_id) do
[
language_switch_item(socket, page_id),
live_item(socket, :support, active_item),
live_item(socket, :settings, active_item),
live_item(socket, :profile, active_item),
user_session_item(socket, :signout, active_item),
user_session_item(socket, :signout, active_item)
]
|> append(live_item(socket, :debug, active_item), feature_enabled?(:debug))
end
Expand Down
4 changes: 3 additions & 1 deletion core/config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,7 @@ config :core,
try do
import_config "dev.secret.exs"
rescue
_ -> IO.puts("Continueing without `dev.secret.exs` file..")
File.Error ->
# Continuing without `dev.secret.exs` file...
nil
end
6 changes: 5 additions & 1 deletion core/lib/core/admin.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
defmodule Core.Admin do
def emails do
Application.get_env(:core, :admins, MapSet.new())
end

def admin?(email) when is_nil(email), do: false

def admin?(email) when is_binary(email) do
Application.get_env(:core, :admins, MapSet.new()) |> MapSet.member?(email)
MapSet.member?(emails(), email)
end

def admin?(%{email: email}) do
Expand Down
2 changes: 2 additions & 0 deletions core/lib/core/authorization.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ defmodule Core.Authorization do

grant_access(CoreWeb.Admin.Login, [:visitor, :member])
grant_access(CoreWeb.Admin.CoordinatorManagement, [:admin])
grant_access(CoreWeb.Admin.SupportTickets, [:admin])
grant_access(CoreWeb.Index, [:visitor, :member])
grant_access(CoreWeb.Support, [:member])
grant_access(CoreWeb.Dashboard, [:researcher])
grant_access(CoreWeb.Marketplace, [:member])
grant_access(CoreWeb.Todo, [:member])
Expand Down
16 changes: 15 additions & 1 deletion core/lib/core/factories.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ defmodule Core.Factories do
Authorization,
DataDonation,
NotificationCenter,
WebPush
WebPush,
Helpdesk
}

alias Core.Repo
Expand All @@ -40,6 +41,11 @@ defmodule Core.Factories do
})
end

def build(:admin) do
:member
|> build(%{email: Core.Admin.emails() |> Enum.random()})
end

def build(:student) do
:member
|> build(%{student: true})
Expand Down Expand Up @@ -72,6 +78,14 @@ defmodule Core.Factories do
}
end

def build(:helpdesk_ticket) do
%Helpdesk.Ticket{
title: Faker.Lorem.sentence(),
description: Faker.Lorem.paragraph(),
user: build(:member)
}
end

def build(:author) do
%Studies.Author{
fullname: Faker.Person.name(),
Expand Down
35 changes: 35 additions & 0 deletions core/lib/core/helpdesk.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule Core.Helpdesk do
@moduledoc """
The Helpdesk context.
"""

import Ecto.Query, warn: false
alias Core.Repo

alias Core.Helpdesk.Ticket

def list_open_tickets do
from(t in Ticket,
where: is_nil(t.completed_at),
order_by: {:asc, :inserted_at},
preload: :user
)
|> Repo.all()
end

def close_ticket_by_id(id) do
from(t in Ticket, where: t.id == ^id)
|> Repo.update_all(set: [completed_at: DateTime.utc_now()])
end

def create_ticket(user, attrs \\ %{}) do
%Ticket{}
|> Ticket.changeset(attrs)
|> Ecto.Changeset.put_assoc(:user, user)
|> Repo.insert()
end

def new_ticket_changeset(attrs \\ %{}) do
Ticket.changeset(%Ticket{}, attrs)
end
end
21 changes: 21 additions & 0 deletions core/lib/core/helpdesk/ticket.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule Core.Helpdesk.Ticket do
use Ecto.Schema
import Ecto.Changeset
alias Core.Accounts.User

schema "helpdesk_tickets" do
belongs_to(:user, User)
field(:description, :string)
field(:title, :string)
field(:completed_at, :utc_datetime)

timestamps()
end

@doc false
def changeset(ticket, attrs) do
ticket
|> cast(attrs, [:title, :description, :completed_at])
|> validate_required([:title, :description])
end
end
1 change: 1 addition & 0 deletions core/lib/core_web/live/admin/routes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule CoreWeb.Live.Admin.Routes do

live("/login", Login)
live("/coordinator-management", CoordinatorManagement)
live("/support-tickets", SupportTickets)
end
end
end
Expand Down
34 changes: 34 additions & 0 deletions core/lib/core_web/live/admin/support_tickets.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule CoreWeb.Admin.SupportTickets do
use CoreWeb, :live_view
alias Core.Helpdesk

data(tickets, :any)

def mount(_params, _session, socket) do
{
:ok,
socket |> assign(:tickets, Helpdesk.list_open_tickets())
}
end

def handle_event("close_ticket", %{"id" => id}, socket) do
Helpdesk.close_ticket_by_id(id)
{:noreply, socket |> assign(:tickets, Helpdesk.list_open_tickets())}
end

def render(assigns) do
~H"""
<div>
Admin
<div :for={{ticket <- @tickets}}>
<h1>{{ticket.title}}</h1>
<p>{{ticket.description}}</p>
<p>
<a href="mailto:{{ticket.user.email}}">Contact {{ticket.user.email}}</a>
</p>
<button :on-click="close_ticket" phx-value-id={{ticket.id}}>Close ticket</button>
</div>
</div>
"""
end
end
1 change: 1 addition & 0 deletions core/lib/core_web/live/layouts/workspace/menu_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ defmodule CoreWeb.Layouts.Workspace.MenuBuilder do
language_switch_item(socket, page_id),
live_item(socket, :settings, active_item),
live_item(socket, :profile, active_item),
live_item(socket, :support, active_item),
user_session_item(socket, :signout, active_item)
]
end
Expand Down
1 change: 1 addition & 0 deletions core/lib/core_web/live/menu/items.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule CoreWeb.Menu.Items do
marketplace: %{target: CoreWeb.Marketplace, domain: "eyra-ui"},
todo: %{target: CoreWeb.Todo, domain: "eyra-ui"},
payments: %{target: CoreWeb.Dashboard, domain: "eyra-ui"},
support: %{target: CoreWeb.Support, domain: "eyra-ui"},
settings: %{target: CoreWeb.User.Settings, domain: "eyra-ui"},
profile: %{target: CoreWeb.User.Profile, domain: "eyra-ui"},
signout: %{target: :delete, domain: "eyra-ui"},
Expand Down
1 change: 1 addition & 0 deletions core/lib/core_web/live/routes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ defmodule CoreWeb.Live.Routes do
live("/marketplace", Marketplace)
live("/todo", Todo)
live("/notifications", Notifications)
live("/support", Support)
end

if Mix.env() in [:dev, :test] do
Expand Down
73 changes: 73 additions & 0 deletions core/lib/core_web/live/support.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
defmodule CoreWeb.Support do
use CoreWeb, :live_view
use CoreWeb.Layouts.Workspace.Component, :support

alias Surface.Components.Form
alias EyraUI.Text.{Title3, BodyLarge}
alias EyraUI.Spacing
alias CoreWeb.Layouts.Workspace.Component, as: Workspace
alias EyraUI.Form.{TextArea, TextInput}
alias EyraUI.Text.{Title3}
alias EyraUI.Button.SubmitButton
alias Core.Helpdesk

data(focus, :any, default: nil)
data(data, :any, default: {})

def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:changeset, Helpdesk.new_ticket_changeset())
|> update_menus()}
end

def handle_event(
"create_ticket",
%{"ticket" => data},
%{assigns: %{current_user: user}} = socket
) do
case Helpdesk.create_ticket(user, data) do
{:ok, _} ->
{:noreply,
socket
|> put_flash(:info, dgettext("eyra-support", "ticket_created.info.flash"))
|> push_redirect(to: Routes.live_path(socket, CoreWeb.Marketplace))}

{:error, changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end

def handle_event("focus", %{"field" => field}, socket) do
{:noreply, assign(socket, :focus, field)}
end

def handle_event("store_state", %{"ticket" => ticket}, socket) do
{:noreply, assign(socket, :changeset, Helpdesk.new_ticket_changeset(ticket))}
end

def render(assigns) do
~H"""
<Workspace
title={{ dgettext("eyra-support", "title") }}
menus={{ @menus }}
>
<ContentArea>
<Title3>{{dgettext("eyra-support", "form.title")}}</Title3>
<BodyLarge>{{dgettext("eyra-support", "form.description")}} </BodyLarge>
<Spacing value="S" />
<div x-data="{ focus: '{{@focus}}' }">
<Form for={{@changeset}} submit="create_ticket" change="store_state">
<TextInput field={{:title}} label_text={{dgettext("eyra-support", "ticket.title.label")}} />
<Spacing value="S" />
<TextArea field={{:description}} label_text={{dgettext("eyra-support", "ticket.description.label")}} />
<SubmitButton label={{ dgettext("eyra-support", "create_ticket.button") }} />
</Form>
</div>
</ContentArea>
</Workspace>
"""
end
end
12 changes: 12 additions & 0 deletions core/priv/gettext/en/LC_MESSAGES/erya-support.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## "msgid"s in this file come from POT (.pot) files.
##
## Do not add, change, or remove "msgid"s manually here as
## they're tied to the ones in the corresponding POT file
## (with the same domain).
##
## Use "mix gettext.extract --merge" or "mix gettext.merge"
## to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2\n"
47 changes: 47 additions & 0 deletions core/priv/gettext/en/LC_MESSAGES/eyra-support.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## "msgid"s in this file come from POT (.pot) files.
##
## Do not add, change, or remove "msgid"s manually here as
## they're tied to the ones in the corresponding POT file
## (with the same domain).
##
## Use "mix gettext.extract --merge" or "mix gettext.merge"
## to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2\n"

#, elixir-format
#: lib/core_web/live/support.ex:64
msgid "form.description"
msgstr "Fill out the form to create a support ticket. We will get back to you via email."

#, elixir-format
#: lib/core_web/live/support.ex:63
msgid "form.title"
msgstr "Create Support Ticket"

#, elixir-format
#: lib/core_web/live/support.ex:70
msgid "ticket.description.label"
msgstr "Description of your support request"

#, elixir-format
#: lib/core_web/live/support.ex:68
msgid "ticket.title.label"
msgstr "Short title for your support request"

#, elixir-format
#: lib/core_web/live/support.ex:58
msgid "title"
msgstr "Support"

#, elixir-format
#: lib/core_web/live/support.ex:72
msgid "create_ticket.button"
msgstr "Submit"

#, elixir-format
#: lib/core_web/live/support.ex:39
msgid "ticket_created.info.flash"
msgstr ""
11 changes: 11 additions & 0 deletions core/priv/gettext/erya-support.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## This file is a PO Template file.
##
## "msgid"s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here as no
## effect: edit them in PO (.po) files instead.
msgid ""
msgstr ""
Loading

0 comments on commit 26934e2

Please sign in to comment.