towerops/lib/towerops/status_pages.ex

115 lines
2.7 KiB
Elixir

defmodule Towerops.StatusPages do
@moduledoc """
Context for white-label customer status pages.
"""
import Ecto.Query
alias Towerops.Repo
alias Towerops.StatusPages.StatusIncident
alias Towerops.StatusPages.StatusPageComponent
alias Towerops.StatusPages.StatusPageConfig
# -- Config --
def get_config_by_org(organization_id) do
StatusPageConfig
|> where(organization_id: ^organization_id)
|> Repo.one()
end
def get_config_by_slug(slug) do
StatusPageConfig
|> where(slug: ^slug, enabled: true)
|> preload([:components, :incidents])
|> Repo.one()
end
def create_config(attrs) do
%StatusPageConfig{}
|> StatusPageConfig.changeset(attrs)
|> Repo.insert()
end
def update_config(%StatusPageConfig{} = config, attrs) do
config
|> StatusPageConfig.changeset(attrs)
|> Repo.update()
end
# -- Components --
def list_components(config_id) do
StatusPageComponent
|> where(status_page_config_id: ^config_id)
|> order_by(asc: :position)
|> Repo.all()
end
def create_component(attrs) do
%StatusPageComponent{}
|> StatusPageComponent.changeset(attrs)
|> Repo.insert()
end
def update_component(%StatusPageComponent{} = component, attrs) do
component
|> StatusPageComponent.changeset(attrs)
|> Repo.update()
end
def delete_component(%StatusPageComponent{} = component) do
Repo.delete(component)
end
# -- Incidents --
def list_incidents(config_id, opts \\ []) do
limit = Keyword.get(opts, :limit, 20)
StatusIncident
|> where(status_page_config_id: ^config_id)
|> order_by(desc: :started_at)
|> limit(^limit)
|> Repo.all()
end
def list_active_incidents(config_id) do
StatusIncident
|> where(status_page_config_id: ^config_id)
|> where([i], i.status != "resolved")
|> order_by(desc: :started_at)
|> Repo.all()
end
def create_incident(attrs) do
%StatusIncident{}
|> StatusIncident.changeset(attrs)
|> Repo.insert()
end
def update_incident(%StatusIncident{} = incident, attrs) do
incident
|> StatusIncident.changeset(attrs)
|> Repo.update()
end
def resolve_incident(%StatusIncident{} = incident) do
update_incident(incident, %{
status: "resolved",
resolved_at: Towerops.Time.now()
})
end
# -- Overall Status --
def overall_status(components) when is_list(components) do
cond do
Enum.any?(components, &(&1.status == "major_outage")) -> :major_outage
Enum.any?(components, &(&1.status == "partial_outage")) -> :partial_outage
Enum.any?(components, &(&1.status == "degraded")) -> :degraded
Enum.any?(components, &(&1.status == "maintenance")) -> :maintenance
true -> :operational
end
end
end