diff --git a/atst/app.py b/atst/app.py index 7d5cc0c6..afaeb6fd 100644 --- a/atst/app.py +++ b/atst/app.py @@ -22,6 +22,7 @@ from atst.domain.authnid.crl import CRLCache, NoOpCRLCache from atst.domain.auth import apply_authentication from atst.domain.authz import Authorization from atst.domain.csp import make_csp_provider +from atst.domain.portfolios import Portfolios from atst.models.permissions import Permissions from atst.eda_client import MockEDAClient from atst.utils import mailer @@ -90,6 +91,14 @@ def make_flask_callbacks(app): g.Authorization = Authorization g.Permissions = Permissions + @app.context_processor + def _portfolios(): + if not g.current_user: + return {} + + portfolios = Portfolios.for_user(g.current_user) + return {"portfolios": portfolios} + @app.after_request def _cleanup(response): g.current_user = None diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py index ac05105f..c1acc655 100644 --- a/atst/routes/__init__.py +++ b/atst/routes/__init__.py @@ -13,6 +13,7 @@ from atst.domain.authnid import AuthenticationContext from atst.domain.audit_log import AuditLog from atst.domain.auth import logout as _logout from atst.domain.common import Paginator +from atst.domain.portfolios import Portfolios from atst.utils.flash import formatted_flash as flash @@ -52,16 +53,16 @@ def home(): if user.atat_role_name == "ccpo": return redirect(url_for("requests.requests_index")) - num_portfolios = len(user.portfolio_roles) + num_portfolios = len([role for role in user.portfolio_roles if role.is_active]) if num_portfolios == 0: return redirect(url_for("requests.requests_index")) elif num_portfolios == 1: portfolio_role = user.portfolio_roles[0] portfolio_id = portfolio_role.portfolio.id - is_request_owner = portfolio_role.role.name == "owner" + is_portfolio_owner = portfolio_role.role.name == "owner" - if is_request_owner: + if is_portfolio_owner: return redirect( url_for("portfolios.portfolio_reports", portfolio_id=portfolio_id) ) @@ -70,7 +71,13 @@ def home(): url_for("portfolios.portfolio_applications", portfolio_id=portfolio_id) ) else: - return redirect(url_for("portfolios.portfolios")) + portfolios = Portfolios.for_user(g.current_user) + first_portfolio = sorted(portfolios, key=lambda portfolio: portfolio.name)[0] + return redirect( + url_for( + "portfolios.portfolio_applications", portfolio_id=first_portfolio.id + ) + ) @bp.route("/styleguide") diff --git a/atst/routes/portfolios/__init__.py b/atst/routes/portfolios/__init__.py index 990c7c2e..ad935378 100644 --- a/atst/routes/portfolios/__init__.py +++ b/atst/routes/portfolios/__init__.py @@ -15,14 +15,12 @@ from atst.models.permissions import Permissions @portfolios_bp.context_processor def portfolio(): - portfolios = Portfolios.for_user(g.current_user) portfolio = None if "portfolio_id" in http_request.view_args: try: portfolio = Portfolios.get( g.current_user, http_request.view_args["portfolio_id"] ) - portfolios = [ws for ws in portfolios if not ws.id == portfolio.id] except UnauthorizedError: pass @@ -33,9 +31,4 @@ def portfolio(): ) return False - return { - "portfolio": portfolio, - "portfolios": portfolios, - "permissions": Permissions, - "user_can": user_can, - } + return {"portfolio": portfolio, "permissions": Permissions, "user_can": user_can} diff --git a/styles/components/_global_layout.scss b/styles/components/_global_layout.scss index ffc02311..a80b4ca5 100644 --- a/styles/components/_global_layout.scss +++ b/styles/components/_global_layout.scss @@ -16,10 +16,6 @@ flex-grow: 1; margin-bottom: $footer-height; - .global-navigation { - margin-top: -1px; - } - .global-panel-container { margin: $gap; max-width: $site-max-width; diff --git a/styles/components/_topbar.scss b/styles/components/_topbar.scss index 54424924..5740b3f9 100644 --- a/styles/components/_topbar.scss +++ b/styles/components/_topbar.scss @@ -1,5 +1,5 @@ .topbar { - background-color: $color-white; + background-color: $color-blue-darkest; border-bottom: 1px solid $color-black; .topbar__navigation { @@ -9,7 +9,7 @@ justify-content: space-between; .topbar__link { - color: $color-black; + color: $color-white; display: inline-flex; align-items: center; height: $topbar-height; @@ -18,10 +18,12 @@ .topbar__link-label { @include h5; + text-decoration: underline; } .topbar__link-icon { margin-left: $gap; + @include icon-color($color-white); } &.topbar__link--home { @@ -29,6 +31,7 @@ .topbar__link-label { padding-left: $gap; + text-decoration: none; } } @@ -45,10 +48,6 @@ &:hover { background-color: $color-primary-darker; color: $color-white; - - .topbar__link-icon { - @include icon-style-inverted; - } } } @@ -62,53 +61,6 @@ .topbar__portfolio-menu { margin-right: auto; position: relative; - - .topbar__portfolio-menu__toggle { - margin: 0; - border-radius: 0; - - &--open { - background-color: $color-blue-darkest; - position: relative; - - &::before { - content: ''; - display: block; - position: absolute; - bottom: 0; - left: $gap * 2; - right: $gap * 2; - height: $gap / 2; - background-color: $color-primary; - } - } - - .icon { - @include icon-size(10); - margin-left: $gap * 2; - } - } - - .topbar__portfolio-menu__panel { - position: absolute; - } - } - - &.topbar__context--portfolio { - background-color: $color-primary; - -ms-flex-pack: start; - - .topbar__link { - color: $color-white; - - .topbar__link-icon { - @include icon-style-inverted; - } - - &:hover { - background-color: $color-primary-darker; - } - } } } } diff --git a/styles/elements/_sidenav.scss b/styles/elements/_sidenav.scss index e335036c..dcfcfe10 100644 --- a/styles/elements/_sidenav.scss +++ b/styles/elements/_sidenav.scss @@ -1,22 +1,54 @@ .sidenav { + @include hide; + + @include media($large-screen) { + @include unhide; + width: 25rem; + margin: 0px; + } + + box-shadow: 0 6px 18px 0 rgba(48,58,65,0.15); + + .sidenav__title { + color: $color-gray-dark; + padding: $gap ($gap * 2); + text-transform: uppercase; + opacity: 0.54; + font-size: $small-font-size; + font-weight: bold; + } + ul { + &.sidenav__list--padded { + margin: 4 * $gap 0; + } + list-style: none; - margin: 0; padding: 0; - li { + li { margin: 0; display: block; } + + } + + .sidenav__divider--small { + display: block; + width: 4 * $gap; + border: 1px solid #D6D7D9; + margin-left: 2 * $gap; + margin-bottom: $gap; } .sidenav__link { display: block; - border-top: 1px solid $color-black; padding: $gap ($gap * 2); color: $color-black; text-decoration: none; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; .sidenav__link-icon { margin-left: - ($gap * .5); @@ -27,16 +59,33 @@ pointer-events: none; } + &.sidenav__link--add { + color: $color-blue; + font-size: $small-font-size; + .icon { + @include icon-color($color-blue); + @include icon-size(14); + } + + } + &.sidenav__link--active { @include h4; color: $color-primary; - background-color: $color-white; + background-color: $color-aqua-lightest; box-shadow: inset ($gap / 2) 0 0 0 $color-primary; .sidenav__link-icon { @include icon-style-active; } + position: relative; + .sidenav__link-active_indicator .icon { + @include icon-color($color-primary); + position: absolute; + right: 0; + } + + ul { background-color: $color-primary; @@ -89,6 +138,7 @@ &:hover { color: $color-primary; + background-color: $color-aqua-lightest; .sidenav__link-icon { @include icon-style-active; @@ -97,3 +147,14 @@ } } } + +.sidenav--minimized { + @extend .sidenav; + + @include unhide; + margin: 0px; + + @include media($large-screen) { + @include hide; + } +} diff --git a/templates/base.html b/templates/base.html index 31d220df..89f56b4a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -21,7 +21,9 @@ {% include 'navigation/topbar.html' %}