Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(theme): add light theme #55

Merged
merged 12 commits into from
Dec 19, 2019
94 changes: 94 additions & 0 deletions cypress/integration/theme.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const A11Y_OPTS = {
runOnly: {
type: "tag",
values: ["section508", "best-practice", "wcag21aa", "wcag2aa"]
}
};

context("Accessibility (a11y)", () => {
context("Logged out", () => {
it.skip("overview", () => {
cy.clearSession();
cy.setTheme("theme-light");
cy.visit("/account/login");
cy.injectAxe();
cy.wait(500);
cy.checkA11y(A11Y_OPTS);
});
});

context("Logged in", () => {
beforeEach(() => {
cy.clearSession();
cy.setTheme("theme-light");
cy.server();
// overview page
cy.route("GET", "*api/v1/repos*", "fixture:overview_page.json");
// add repos page
cy.route(
"GET",
"*api/v1/user/source/repos*",
"fixture:add_repositories.json"
);
// settings page
cy.route("GET", "*api/v1/repos/*/octocat", "fixture:repository.json");
// repo and build page
cy.stubBuilds();
cy.stubBuild();
cy.stubStepsWithLogs();
// hooks page
cy.route("GET", "*api/v1/hooks/github/octocat*", "fixture:hooks_5.json");
cy.route(
"GET",
"*api/v1/repos/*/octocat/builds/1*",
"fixture:build_success.json"
);
cy.route(
"GET",
"*api/v1/repos/*/octocat/builds/2*",
"fixture:build_failure.json"
);
cy.route(
"GET",
"*api/v1/repos/*/octocat/builds/3*",
"fixture:build_running.json"
);
});
after(() => {
cy.visit("/");
cy.server({ enable: false });
});

it.skip("overview", () => {
cy.checkA11yForPage("/", A11Y_OPTS);
});

it.skip("add repos", () => {
cy.checkA11yForPage("/account/add-repos", A11Y_OPTS);
});

it.skip("settings", () => {
cy.checkA11yForPage("/github/octocat/settings", A11Y_OPTS);
});

it.skip("repo page", () => {
cy.checkA11yForPage("/someorg/somerepo", A11Y_OPTS);
});

it.skip("hooks page", () => {
cy.login("/github/octocat/hooks");
cy.injectAxe();
cy.wait(500);
cy.get("[data-test=hook]").click({ multiple: true });
cy.checkA11y(A11Y_OPTS);
});

it.skip("build page", () => {
cy.login("/someorg/somerepo/1");
cy.injectAxe();
cy.wait(500);
cy.get("[data-test=step-header]").click({ multiple: true });
cy.checkA11y(A11Y_OPTS);
});
});
});
6 changes: 6 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,9 @@ Cypress.Commands.add("checkA11yForPage", (path = "/", opts = {}) => {
cy.wait(500);
cy.checkA11y(opts);
});

Cypress.Commands.add("setTheme", theme => {
cy.window().then(win => {
win.localStorage.setItem("vela-theme", theme);
});
});
2 changes: 1 addition & 1 deletion src/elm/Build.elm
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ buildStatusStyles markdown buildStatus buildNumber =
[ div [ class "build-animation", class "-not-running", statusToClass buildStatus ] []
]
in
List.append animation markdown
markdown ++ animation


{-| topParticles : returns an svg frame to parallax scroll on a running build, set to the top of the build
Expand Down
22 changes: 18 additions & 4 deletions src/elm/Interop.elm
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,35 @@ Use of this source code is governed by the LICENSE file in this repository.
--}


port module Interop exposing (onSessionChange, storeSession)
port module Interop exposing (onSessionChange, onThemeChange, setTheme, storeSession)

import Json.Decode as Decode
import Json.Encode as Encode



-- inbound port
-- SESSION


{-| inbound
-}
port onSessionChange : (Decode.Value -> msg) -> Sub msg


{-| outbound
-}
port storeSession : Encode.Value -> Cmd msg

-- outbound port


port storeSession : Encode.Value -> Cmd msg
-- THEME


{-| inbound
-}
port onThemeChange : (Decode.Value -> msg) -> Sub msg


{-| outbound
-}
port setTheme : Encode.Value -> Cmd msg
52 changes: 48 additions & 4 deletions src/elm/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,25 @@ import Vela
, Step
, StepNumber
, Steps
, Theme(..)
, UpdateRepositoryPayload
, User
, Viewing
, buildUpdateRepoBoolPayload
, buildUpdateRepoIntPayload
, buildUpdateRepoStringPayload
, decodeSession
, decodeTheme
, defaultAddRepositoryPayload
, defaultBuilds
, defaultHooks
, defaultRepository
, defaultSession
, encodeAddRepository
, encodeSession
, encodeTheme
, encodeUpdateRepository
, stringToTheme
)


Expand All @@ -138,6 +142,7 @@ type alias Flags =
, velaFeedbackURL : String
, velaDocsURL : String
, velaSession : Maybe Session
, velaTheme : String
}


Expand Down Expand Up @@ -165,6 +170,7 @@ type alias Model =
, inTimeout : Maybe Int
, entryURL : Url
, hookBuilds : HookBuilds
, theme : Theme
}


Expand Down Expand Up @@ -226,6 +232,7 @@ init flags url navKey =
, inTimeout = Nothing
, entryURL = url
, hookBuilds = Dict.empty
, theme = stringToTheme flags.velaTheme
}

( newModel, newPage ) =
Expand All @@ -240,6 +247,9 @@ init flags url navKey =
( newModel
, Cmd.batch
[ newPage

-- for themes, we rely on ports to apply the class on <body>
, Interop.setTheme <| encodeTheme model.theme
, setTimeZone
, setTime
]
Expand All @@ -259,6 +269,7 @@ type Msg
| ChangeRepoTimeout String
| RefreshSettings Org Repo
| ClickHook Org Repo BuildNumber
| SetTheme Theme
| ClickLogLine Org Repo BuildNumber StepNumber Int
| ClickStep Org Repo (Maybe BuildNumber) (Maybe StepNumber)
| GotoPage Pagination.Page
Expand Down Expand Up @@ -584,6 +595,13 @@ update msg model =
, action
)

SetTheme theme ->
if theme == model.theme then
( model, Cmd.none )

else
( { model | theme = theme }, Interop.setTheme <| encodeTheme theme )

ClickLogLine org repo buildNumber stepNumber lineNumber ->
let
( steps, action ) =
Expand Down Expand Up @@ -714,6 +732,7 @@ subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ Interop.onSessionChange decodeOnSessionChange
, Interop.onThemeChange decodeOnThemeChange
, every Util.oneSecondMillis <| Tick OneSecond
, every Util.fiveSecondsMillis <| Tick (FiveSecond <| refreshData model)
]
Expand All @@ -734,6 +753,16 @@ decodeOnSessionChange sessionJson =
SessionChanged Nothing


decodeOnThemeChange : Decode.Value -> Msg
decodeOnThemeChange inTheme =
case Decode.decodeValue decodeTheme inTheme of
Ok theme ->
SetTheme theme

Err _ ->
SetTheme Dark


{-| refreshPage : refreshes Vela data based on current page and build status
-}
refreshPage : Model -> RefreshData -> Cmd Msg
Expand Down Expand Up @@ -917,7 +946,7 @@ view model =
in
{ title = "Vela - " ++ title
, body =
[ lazy2 viewHeader model.session { feedbackLink = model.velaFeedbackURL, docsLink = model.velaDocsURL }
[ lazy2 viewHeader model.session { feedbackLink = model.velaFeedbackURL, docsLink = model.velaDocsURL, theme = model.theme }
, viewNav model
, div [ class "util" ] [ Build.viewBuildHistory model.time model.zone model.page model.builds.org model.builds.repo model.builds.builds ]
, main_ []
Expand Down Expand Up @@ -1425,8 +1454,8 @@ navButton model =
text ""


viewHeader : Maybe Session -> { feedbackLink : String, docsLink : String } -> Html Msg
viewHeader maybeSession { feedbackLink, docsLink } =
viewHeader : Maybe Session -> { feedbackLink : String, docsLink : String, theme : Theme } -> Html Msg
viewHeader maybeSession { feedbackLink, docsLink, theme } =
let
session : Session
session =
Expand All @@ -1452,13 +1481,28 @@ viewHeader maybeSession { feedbackLink, docsLink } =
]
]
, div [ class "help-links" ]
[ a [ href feedbackLink, attribute "aria-label" "go to feedback" ] [ text "feedback" ]
[ viewThemeToggle theme
, a [ href feedbackLink, attribute "aria-label" "go to feedback" ] [ text "feedback" ]
, a [ href docsLink, attribute "aria-label" "go to docs" ] [ text "docs" ]
, FeatherIcons.terminal |> FeatherIcons.withSize 18 |> FeatherIcons.toHtml []
]
]


viewThemeToggle : Theme -> Html Msg
viewThemeToggle theme =
let
( newTheme, icon, themeAria ) =
case theme of
Dark ->
( Light, SvgBuilder.themeLight, "activate light mode" )

Light ->
( Dark, SvgBuilder.themeDark, "activate dark mode" )
in
button [ class "theme-toggle", attribute "aria-label" themeAria, onClick (SetTheme newTheme) ] [ icon 24 ]



-- HELPERS

Expand Down
12 changes: 11 additions & 1 deletion src/elm/Main/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export type Flags = {
readonly velaDocsURL: string;
/** @property velaSession used for passsing in an existing Vela session to Elm */
readonly velaSession: Session | null;
/** @property velaTheme: Theme | null */
readonly velaTheme: Theme;
};

/**
Expand All @@ -66,6 +68,8 @@ export type Flags = {
export type Ports = {
readonly storeSession: ToJS<Session>;
readonly onSessionChange: ToElm<Session>;
readonly setTheme: ToJS<Theme>;
readonly onThemeChange: ToElm<Theme>;
};

/**
Expand All @@ -86,11 +90,17 @@ export type ToElm<T> = {
};

/**
* The format of the session that we are working with in Vela
* The shape of session that we are working with in Vela
*
*/
export type Session = {
readonly username: string;
readonly token: string;
readonly entrypoint: string;
};

/**
* Supported themes
*
*/
export type Theme = "theme-light" | "theme-dark";
Loading