Skip to content

Commit

Permalink
feat(Alerts): Added back the lifecycle labels (#2095)
Browse files Browse the repository at this point in the history
  • Loading branch information
kotva006 authored Jun 17, 2024
1 parent c0268f9 commit 2a0164a
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 2 deletions.
14 changes: 14 additions & 0 deletions assets/css/_alerts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@
margin-top: $space-12;
}

.c-alert-item__badge {
background-color: $service-alert-yellow-darker;
border-radius: calc(#{$base-spacing} / 4);
padding: calc(#{$base-spacing} / 8) calc(#{$base-spacing} / 2);
}

.c-alert-item__badge--upcoming {
background-color: $service-alert-gray-darker;
}

.c-alert-item__badge--system {
background-color: $service-alert-yellow;
}

.m-alerts__mode-buttons {
display: flex;
margin-left: calc(-#{$grid-gutter-width} / 4);
Expand Down
35 changes: 34 additions & 1 deletion assets/ts/components/Alerts.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { ReactElement, useState } from "react";
import { Alert as AlertType } from "../__v3api";
import { Alert as AlertType, Lifecycle } from "../__v3api";
import { handleReactEnterKeyPress } from "../helpers/keyboard-events-react";
import { caret } from "../helpers/icon";
import renderSVG from "../helpers/render-svg";
Expand Down Expand Up @@ -47,6 +47,38 @@ export const iconForAlert = ({
}
};

export const humanLifecycle = (lifecycle: Lifecycle): string | null => {
switch (lifecycle) {
case "upcoming":
case "ongoing_upcoming":
return "Upcoming";
case "ongoing":
return "Ongoing";
case "new":
case "unknown":
default:
return null;
}
};

export const alertLabel = (alert: AlertType): ReactElement<HTMLElement> => {
const alertClasses = ["u-small-caps", "c-alert-item__badge"];
if (alert.priority === "system") {
alertClasses.push("c-alert-item__badge--system");
}
if (
alert.lifecycle === "upcoming" ||
alert.lifecycle === "ongoing_upcoming"
) {
alertClasses.push("c-alert-item__badge--upcoming");
}
return (
<span className={alertClasses.join(" ")}>
{humanLifecycle(alert.lifecycle)}
</span>
);
};

export const effectNameForAlert = (alert: AlertType): string =>
alert.effect
.split("_")
Expand Down Expand Up @@ -195,6 +227,7 @@ export const Alert = ({
<div className="c-alert-item__top-text-container">
<div className="c-alert-item__effect">
{`${effectNameForAlert(alert)} `}
{humanLifecycle(alert.lifecycle) ? alertLabel(alert) : null}
</div>
{/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{ __html: headerContent }} />
Expand Down
32 changes: 31 additions & 1 deletion assets/ts/components/__tests__/AlertsTest.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { mount } from "enzyme";
import renderer from "react-test-renderer";
import Alerts, { iconForAlert } from "../Alerts";
import Alerts, { alertLabel, iconForAlert, humanLifecycle } from "../Alerts";
import { enzymeToJsonWithoutProps } from "../../app/helpers/testUtils";
import { Alert, InformedEntitySet } from "../../__v3api";
import { isAmenityAlert } from "../../models/alert";
Expand Down Expand Up @@ -168,6 +168,36 @@ describe("iconForAlert", () => {
);
});

describe("alertLabel", () => {
test("it returns a system label for system alerts", () => {
const label = alertLabel({
...highAlert,
priority: "system",
lifecycle: "ongoing_upcoming"
});
const labelComponent = JSON.stringify(renderer.create(label!).toJSON());
expect(labelComponent).toMatch("badge--system");
expect(labelComponent).toMatch("badge--upcoming");
});
});

describe("humanLifecycle", () => {
it("returns correct value for others", () => {
let label = humanLifecycle("ongoing_upcoming");
expect(label).toMatch("Upcoming");
label = humanLifecycle("ongoing");
expect(label).toMatch("Ongoing");
label = humanLifecycle("upcoming");
expect(label).toMatch("Upcoming");
label = humanLifecycle("new");
expect(label).toBeNull();
label = humanLifecycle("unknown");
expect(label).toBeNull();
label = humanLifecycle("something" as any);
expect(label).toBeNull();
});
});

test("renders alert icon for system alerts", () => {
const icon = iconForAlert({
...highAlert,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ exports[`it renders 1`] = `
className="c-alert-item__effect"
>
Other
<span
className="u-small-caps c-alert-item__badge c-alert-item__badge--upcoming"
>
Upcoming
</span>
</div>
<div
dangerouslySetInnerHTML={
Expand Down
8 changes: 8 additions & 0 deletions lib/alerts/alert.ex
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ defmodule Alerts.Alert do
defp do_human_lifecycle(:ongoing), do: "Ongoing"
defp do_human_lifecycle(_), do: "Unknown"

@spec human_label(t) :: String.t()
def human_label(%{lifecycle: lifecycle})
when lifecycle not in [:new, :unknown] do
do_human_lifecycle(lifecycle)
end

def human_label(_), do: ""

@spec icon(t) :: icon_type
def icon(%{priority: :low}), do: :none
def icon(%{priority: :high, effect: :suspension}), do: :cancel
Expand Down
14 changes: 14 additions & 0 deletions lib/dotcom_web/banneralert.ex
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
defprotocol BannerAlert do
def header(obj)
def human_effect(obj)
def human_label(obj)
def icon(obj)
def label_class(obj)
end

defimpl BannerAlert, for: Alerts.Alert do
def header(alert), do: alert.header
defdelegate human_effect(alert), to: Alerts.Alert
defdelegate human_label(alert), to: Alerts.Alert
defdelegate icon(alert), to: Alerts.Alert
def label_class(alert), do: DotcomWeb.AlertView.alert_label_class(alert)
end

defimpl BannerAlert, for: Alerts.Banner do
Expand All @@ -18,11 +22,21 @@ defimpl BannerAlert, for: Alerts.Banner do
|> Alerts.Alert.human_effect()
end

def human_label(banner) do
alert_from_banner(banner)
|> Alerts.Alert.human_label()
end

def icon(banner) do
alert_from_banner(banner)
|> Alerts.Alert.icon()
end

def label_class(banner) do
alert_from_banner(banner)
|> DotcomWeb.AlertView.alert_label_class()
end

defp alert_from_banner(banner) do
Alerts.Alert
|> struct(Map.from_struct(banner))
Expand Down
4 changes: 4 additions & 0 deletions lib/dotcom_web/templates/alert/_banner.html.eex
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% label = BannerAlert.human_label(@alert) %>
<div tabindex="0" class="c-alert-item c-alert-item--system">
<div class="c-alert-item__icon">
<%= @alert |> BannerAlert.icon() |> alert_icon() %>
Expand All @@ -6,6 +7,9 @@
<div class="c-alert-item__top-text-container">
<div class="c-alert-item__effect">
<%= "#{BannerAlert.human_effect(@alert)} " %>
<%= unless label == "" do
content_tag(:span, [label], class: BannerAlert.label_class(@alert))
end %>
</div>
<div class="c-alert-item__content">
<%= replace_urls_with_links(BannerAlert.header(@alert)) %>
Expand Down
4 changes: 4 additions & 0 deletions lib/dotcom_web/templates/alert/_item.html.eex
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% label = Alerts.Alert.human_label(@alert) %>
<% alert_icon_type = Alerts.Alert.icon(@alert) %>
<li tabindex="0"
class="c-alert-item c-alert-item--<%= @alert.priority %>
Expand All @@ -11,6 +12,9 @@
<div class="c-alert-item__top-text-container">
<div class="c-alert-item__effect">
<%= "#{effect_name(@alert)} " %>
<%= unless label == "" do
content_tag(:span, [label], class: alert_label_class(@alert))
end %>
</div>
<div class="c-alert-item__content">
<%= replace_urls_with_links(@alert.header) %>
Expand Down
20 changes: 20 additions & 0 deletions lib/dotcom_web/views/alert_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,26 @@ defmodule DotcomWeb.AlertView do
Alert.human_effect(alert)
end

def alert_label_class(%Alert{} = alert) do
["u-small-caps", "c-alert-item__badge"]
|> do_alert_label_class(alert)
|> Enum.join(" ")
end

defp do_alert_label_class(class_list, %Alert{priority: priority})
when priority == :system do
["c-alert-item__badge--system" | class_list]
end

defp do_alert_label_class(class_list, %Alert{lifecycle: lifecycle})
when lifecycle in [:upcoming, :ongoing_upcoming] do
["c-alert-item__badge--upcoming" | class_list]
end

defp do_alert_label_class(class_list, _) do
class_list
end

def alert_updated(%Alert{updated_at: updated_at}, relative_to) do
alert_updated(updated_at, relative_to)
end
Expand Down
36 changes: 36 additions & 0 deletions test/alerts/alerts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,42 @@ defmodule AlertsTest do
end
end

describe "human_label/1" do
@future_active_period [{Timex.shift(@now, days: 8), Timex.shift(@now, days: 20)}]

test "returns Ongoing when lifecycle is ongoing and time not in active period" do
assert human_label(%Alert{
effect: :cancellation,
active_period: @future_active_period,
lifecycle: :ongoing
}) == "Ongoing"
end

test "returns Upcoming when lifecycle is ongoing and time not in active period" do
assert human_label(%Alert{
effect: :cancellation,
active_period: @future_active_period,
lifecycle: :upcoming
}) == "Upcoming"
end

test "returns empty string when lifecycle is new and time not in active period" do
assert human_label(%Alert{
effect: :cancellation,
active_period: @future_active_period,
lifecycle: :new
}) == ""
end

test "returns Upcoming when lifecycle is upcoming and active period is empty" do
assert human_label(%Alert{
effect: :cancellation,
active_period: [],
lifecycle: :upcoming
}) == "Upcoming"
end
end

describe "icon/1" do
test "return :none, :cancel, :snow, :shuttle or :alert" do
assert icon(%Alert{effect: :detour, priority: :low}) == :none
Expand Down
17 changes: 17 additions & 0 deletions test/dotcom_web/banneralert_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ defmodule BannerAlertTest do
end
end

describe "BannerAlert.human_label" do
test "for Alerts.Banner" do
assert BannerAlert.human_label(@banner) == ""
end
end

describe "BannerAlert.icon" do
test "for Alerts.Alert" do
assert BannerAlert.icon(@alert) == :none
Expand All @@ -36,4 +42,15 @@ defmodule BannerAlertTest do
assert BannerAlert.icon(@banner) == :alert
end
end

describe "BannerAlert.label_class" do
test "for Alerts.Alert" do
assert BannerAlert.label_class(@alert) == "u-small-caps c-alert-item__badge"
end

test "for Alerts.Banner" do
assert BannerAlert.label_class(@banner) ==
"c-alert-item__badge--system u-small-caps c-alert-item__badge"
end
end
end

0 comments on commit 2a0164a

Please sign in to comment.