Packages

An open source two way communication platform for the social sector

Current section

Files

Jump to
glific lib glific_web flows flow_editor_controller.ex
Raw

lib/glific_web/flows/flow_editor_controller.ex

defmodule GlificWeb.Flows.FlowEditorController do
@moduledoc """
The Flow Editor Controller
"""
use GlificWeb, :controller
alias Glific.{
Flows,
Flows.ContactField,
Flows.Flow,
Flows.FlowCount
}
@doc false
@spec globals(Plug.Conn.t(), map) :: Plug.Conn.t()
def globals(conn, _params) do
conn
|> json(%{results: []})
end
@doc false
@spec groups(Plug.Conn.t(), map) :: Plug.Conn.t()
def groups(conn, _params) do
group_list =
Glific.Groups.list_groups(%{filter: %{organization_id: conn.assigns[:organization_id]}})
|> Enum.reduce([], fn group, acc ->
[%{uuid: "#{group.id}", name: group.label} | acc]
end)
conn
|> json(%{results: group_list})
end
@doc false
@spec groups_post(Plug.Conn.t(), map) :: Plug.Conn.t()
def groups_post(conn, params) do
conn
|> json(%{
uuid: generate_uuid(),
query: nil,
status: "ready",
count: 0,
name: params["name"]
})
end
@doc false
@spec fields(Plug.Conn.t(), map) :: Plug.Conn.t()
def fields(conn, _params) do
fields =
ContactField.list_contacts_fields(%{
filter: %{organization_id: conn.assigns[:organization_id]}
})
|> Enum.reduce([], fn cf, acc ->
[%{key: cf.shortcode, name: cf.name, value_type: cf.value_type} | acc]
end)
json(conn, %{results: fields})
end
@doc """
Add Contact fields into the database. The response should be a map with 3 keys
% { Key: Field name, name: Field display name value_type: type of the value}
We are not supporting this for now. We will add that in future
"""
@spec fields_post(Plug.Conn.t(), map) :: Plug.Conn.t()
def fields_post(conn, params) do
# need to store this into DB, the value_type will default to text in this case
# the shortcode is the name, lower cased, and camelized
{:ok, contact_field} =
ContactField.create_contact_field(%{
name: params["label"],
shortcode: Glific.string_clean(params["label"]),
organization_id: conn.assigns[:organization_id]
})
conn
|> json(%{
key: contact_field.shortcode,
name: contact_field.name,
value_type: contact_field.value_type
})
end
@doc """
Get all the tags so that user can apply them on incoming message.
We are not supporting this for now. To enable It should return a list of map having
uuid and name as keys
[%{uuid: tag.uuid, name: tag.label}]
"""
@spec labels(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def labels(conn, _params) do
tag_list =
Glific.Tags.list_tags(%{
filter: %{parent: "Contacts", organization_id: conn.assigns[:organization_id]}
})
|> Enum.reduce([], fn tag, acc ->
[%{uuid: "#{tag.id}", name: tag.label} | acc]
end)
json(conn, %{results: tag_list})
end
@doc """
Store a lable (new tag) in the system. The return response should be a map of 3 keys.
[%{uuid: tag.uuid, name: params["name"], count}]
We are not supporting them for now. We will come back to this in near future
"""
@spec labels_post(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def labels_post(conn, _params) do
json(conn, %{})
end
@doc """
A list of all the communication channels. For Glific it's just WhatsApp.
We are not supporting them for now. We will come back to this in near future
"""
@spec channels(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def channels(conn, _params) do
channels = %{
results: [
%{
uuid: generate_uuid(),
name: "WhatsApp",
address: "",
schemes: ["whatsapp"],
roles: ["send", "receive"]
}
]
}
json(conn, channels)
end
@doc """
A list of all the communication channels. For Glific it's just WhatsApp.
We are not supporting them for now. We will come back to this in near future
"""
@spec classifiers(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def classifiers(conn, _params) do
classifiers = %{results: []}
json(conn, classifiers)
end
@doc """
We are not sure how to use this but this endpoint is required for flow editor.
Will come back to this in future.
"""
@spec ticketers(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def ticketers(conn, _params) do
ticketers = %{results: []}
json(conn, ticketers)
end
@doc """
We are not using this for now but this is required for flow editor config.
"""
@spec resthooks(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def resthooks(conn, _params) do
resthooks = %{results: []}
json(conn, resthooks)
end
@doc false
@spec templates(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def templates(conn, _params) do
results =
Glific.Templates.list_session_templates(%{
filter: %{organization_id: conn.assigns[:organization_id]}
})
|> Enum.reduce([], fn template, acc ->
template = Glific.Repo.preload(template, :language)
language = template.language
[
%{
uuid: template.uuid,
name: template.label,
created_on: template.inserted_at,
modified_on: template.updated_at,
translations: [
%{
language: language.locale,
content: template.body,
variable_count: template.number_parameters,
status: "approved",
channel: %{uuid: "", name: "WhatsApp"}
}
]
}
| acc
]
end)
json(conn, %{results: results})
end
@doc false
@spec languages(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def languages(conn, _params) do
results =
Glific.Settings.list_languages()
|> Enum.reduce([], fn language, acc ->
[%{iso: language.label, name: language.label} | acc]
end)
json(conn, %{results: results})
end
@doc false
@spec environment(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def environment(conn, _params) do
environment = %{}
json(conn, environment)
end
@doc false
@spec recipients(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def recipients(conn, _params) do
recipients = %{results: []}
json(conn, recipients)
end
@doc """
instead of reading a file we can call it directly from Assests.
We will come back on that when we have more clearity of the use cases
"""
@spec completion(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def completion(conn, _params) do
completion =
File.read!(Path.join(:code.priv_dir(:glific), "data/flows/completion.json"))
|> Jason.decode!()
json(conn, completion)
end
@doc """
This is used to checking if the connection between frontend and backend is established or not.
"""
@spec activity(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def activity(conn, params) do
{nodes, segments, recent_messages} =
FlowCount.get_flow_count_list(params["flow"])
|> Enum.reduce(
{%{}, %{}, %{}},
fn fc, acc ->
{nodes, segments, recent_messages} = acc
case fc.type do
"node" ->
{Map.put(nodes, fc.uuid, fc.count), segments, recent_messages}
"exit" ->
key = "#{fc.uuid}:#{fc.destination_uuid}"
{
nodes,
Map.put(segments, key, fc.count),
Map.put(recent_messages, key, get_recent_message(fc))
}
_ ->
acc
end
end
)
activity = %{nodes: nodes, segments: segments, recentMessages: recent_messages}
json(conn, activity)
end
defp get_recent_message(flow_count) do
# flow editor shows only last 3 messages. We are just tacking 5 for the safe side.
flow_count.recent_messages
|> Enum.map(fn msg -> %{text: msg["message"], sent: msg["date"]} end)
|> Enum.take(5)
end
@doc """
Let's get all the flows or a latest flow revision
"""
@spec flows(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def flows(conn, %{"vars" => vars}) do
results =
case vars do
[] ->
## We need to fix this before merging this branch
Flows.list_flows(%{filter: %{organization_id: conn.assigns[:organization_id]}})
|> Enum.reduce([], fn flow, acc ->
[
%{
uuid: flow.uuid,
name: flow.name,
type: flow.flow_type,
archived: false,
labels: [],
expires: 10_080,
parent_refs: []
}
| acc
]
end)
[flow_uuid] ->
with {:ok, flow} <-
Glific.Repo.fetch_by(Flow, %{
uuid: flow_uuid,
organization_id: conn.assigns[:organization_id]
}),
do: Flow.get_latest_definition(flow.id)
end
json(conn, %{results: results})
end
@doc """
Get all or a specific revision for a flow
"""
@spec revisions(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def revisions(conn, %{"vars" => vars}) do
case vars do
[flow_uuid] -> json(conn, Flows.get_flow_revision_list(flow_uuid))
[flow_uuid, revison_id] -> json(conn, Flows.get_flow_revision(flow_uuid, revison_id))
end
end
@doc """
Save a revision for a flow and get the revision id
"""
@spec save_revisions(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def save_revisions(conn, params) do
revision = Flows.create_flow_revision(params)
json(conn, %{revision: revision.id})
end
@doc """
all the supported funcations we provide
"""
@spec functions(Plug.Conn.t(), nil | maybe_improper_list | map) :: Plug.Conn.t()
def functions(conn, _) do
functions =
File.read!(Path.join(:code.priv_dir(:glific), "data/flows/functions.json"))
|> Jason.decode!()
json(conn, functions)
end
@doc false
@spec generate_uuid() :: String.t()
defp generate_uuid do
Ecto.UUID.generate()
end
end