Merge branch 'master' into ui/styleguide

This commit is contained in:
luisgov 2018-07-24 13:58:22 -04:00 committed by GitHub
commit 8d671b238b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 264 additions and 69 deletions

View File

@ -58,6 +58,19 @@ To start the app locally in the foreground and watch for changes:
script/dev_server
### Users
There are currently six mock users for development:
- Sam (a CCPO)
- Amanda
- Brandon
- Christina
- Dominick
- Erica
To log in as one of them, navigate to `/login-dev?username=<lowercase name>`. For example `/login-dev?username=amanda`.
## Testing
To run lint, static analysis, and unit tests:
@ -86,3 +99,17 @@ To render an icon use `{% module Icon('name') %}` in a template, where `name` is
All icons used should be from the Noun Project, specifically [this collection](https://thenounproject.com/monstercritic/collection/tinicons-a-set-of-tiny-icons-perfect-for-ui-elemen/) if possible.
SVG markup should be cleaned an minified, [Svgsus](http://www.svgs.us/) works well.
## Deployment
The `/login-dev` endpoint is protected by HTTP basic auth when deployed. This can be configured for NGINX following the instructions [here](https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/). The following config should added within the main server block for the site:
```
location /login-dev {
auth_basic "Developer Access";
auth_basic_user_file /etc/apache2/.htpasswd;
[proxy information should follow this]
}
```
The location block will require the same proxy pass configuration as other location blocks for the app.

View File

@ -6,7 +6,7 @@ _DEV_USERS = {
"sam": {
"id": "164497f6-c1ea-4f42-a5ef-101da278c012",
"first_name": "Sam",
"last_name": "CCPO",
"last_name": "Seeceepio",
"atat_role": "ccpo"
},

View File

@ -5,3 +5,12 @@ def dev(self):
def matchesPath(self, href):
return self.request.uri.startswith(href)
def modal(self, body):
return self.render_string(
"components/modal.html.to",
body=body)
def modalOpen(self):
# For now, just check a dummy URL param
return self.get_argument("modal", False)

View File

@ -16,10 +16,11 @@ class Icon(UIModule):
"components/icon.html.to", svg=svg.read(), name=name, classes=classes)
class SidenavItem(UIModule):
def render(self, label, href, active=False, icon=None):
def render(self, label, href, active=False, icon=None, subnav=None):
return self.render_string(
"navigation/_sidenav_item.html.to",
label=label,
href=href,
active=active,
icon=icon)
icon=icon,
subnav=subnav)

View File

@ -12,6 +12,7 @@
@import 'elements/tables';
@import 'elements/icons';
@import 'elements/sidenav';
@import 'elements/action_group';
@import 'components/layout';
@import 'components/topbar';
@ -19,6 +20,7 @@
@import 'components/site_action';
@import 'components/empty_state';
@import 'components/alerts';
@import 'components/modal';
@import 'sections/footer';
@import 'sections/login';

View File

@ -44,6 +44,7 @@
.alert__title {
@include h3;
margin-top: 0;
}
.alert__content {

View File

@ -8,6 +8,10 @@ body {
> footer {
margin-top: auto;
}
&.modalOpen {
overflow-y: hidden;
}
}
.global-layout {

View File

@ -0,0 +1,47 @@
.modal {
position: fixed;
z-index: 3;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: $color-overlay;
.modal__dialog {
padding: $gap;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
@include media($medium-screen) {
padding: $gap * 2;
}
@include media($large-screen) {
padding: $gap * 4;
}
.modal__body {
background-color: $color-white;
padding: $gap * 2;
flex-grow: 1;
overflow-y: auto;
max-width: 80rem;
@include media($medium-screen) {
padding: $gap * 4;
flex-grow: 0;
}
h1, h2 {
@include h3;
}
:first-child {
margin-top: 0;
}
}
}
}

View File

@ -106,6 +106,7 @@ $color-base: $color-black-light;
$color-focus: $color-gray-light;
$color-visited: $color-purple;
$color-overlay: rgba(#000, 0.5);
$color-shadow: rgba(#000, 0.3);
$color-transparent: rgba(#000, 0);

View File

@ -0,0 +1,14 @@
.action-group {
display: flex;
flex-direction: row-reverse;
align-items: center;
margin-top: $gap * 4;
.action-group__action {
margin: 0 0 0 ($gap * 2);
}
&:last-child {
margin-bottom: $gap * 3;
}
}

View File

@ -4,10 +4,6 @@
* @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_inputs.scss
*/
from {
margin-bottom: 3rem;
}
select {
border-radius: 0;
-webkit-appearance: none;
@ -28,3 +24,19 @@ select {
padding-bottom: 0.5rem;
}
}
.usa-search {
padding-top: 2px;
margin-right: 2rem;
input[type=search] {
height: 4.4rem;
font-size: 1.7rem;
color: $color-black;
}
button {
min-height: 4.4rem;
}
}

View File

@ -43,4 +43,4 @@
padding: 0 ($gap * 4);
}
}
}
}

View File

@ -44,6 +44,7 @@
&--active {
@include h5;
color: $color-primary;
box-shadow: none;
}
}
}
@ -55,9 +56,21 @@
li {
.sidenav__link {
@include h5;
padding: ($gap * .75) ($gap * 3);
padding: $gap * .75;
padding-left: 4.5rem;
border: 0;
font-weight: normal;
.sidenav__link-icon {
@include icon-size(12);
flex-shrink: 0;
margin-right: 1.5rem;
margin-left: -3rem
}
.sidenav__link-label {
padding-left: 0;
}
}
}
}

View File

@ -4,7 +4,7 @@
* @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_table.scss
*/
table {
table {
@include panel-margin;
min-width: 100%;

View File

@ -9,25 +9,14 @@
-moz-osx-font-smoothing: grayscale;
}
p {
margin: 0 0 ($gap * 2) 0;
max-width: 45em;
}
h1, h2, h3, h4, h5, h6 {
font-family: $font-sans;
.usa-button {
position: relative;
bottom: 0.5rem;
left: 1rem;
}
}
h1 {
margin-top: 0.5em;
margin-bottom: 0;
}
h2 {
margin-top: 0;
color: $color-gray;
margin: ($gap * 2) 0;
}
a,

1
static/icons/plus.svg Normal file
View File

@ -0,0 +1 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M6.966 6.992V1.009C6.988.417 7.322-.052 8.091.005c.505.074.884.488.903 1.004v5.966c2.049-.012 4.096-.002 6.143.073 1.031.113 1.292 1.968-.074 2.017H8.994v6.037c-.039 1.076-1.98 1.313-2.028 0V9.065H.898c-1.076-.039-1.313-1.972 0-2.02 2.022 0 4.045-.031 6.068-.053z" fill-rule="nonzero"/></svg>

After

Width:  |  Height:  |  Size: 452 B

View File

@ -13,7 +13,7 @@
{% end %}
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico">
</head>
<body>
<body class="{% if modalOpen() %} modalOpen{% end %}">
{% include 'navigation/topbar.html.to' %}
<div class='global-layout'>
@ -29,6 +29,8 @@
</div>
{% include 'footer.html.to' %}
{% block modal %}{% end %}
</body>
</html>

View File

@ -0,0 +1,7 @@
<div class='modal'>
<div class='modal__dialog' role='dialog' aria-modal='true'>
<div class='modal__body'>
{% raw body %}
</div>
</div>
</div>

View File

@ -6,4 +6,19 @@
<span class="sidenav__link-label">{{label}}</span>
</a>
{% if subnav and active %}
<ul>
{% for item in subnav %}
<li>
<a class="sidenav__link {% if item["active"] %}sidenav__link--active{% end %}" href="{{item["href"]}}" title="{{item["label"]}}">
{% if "icon" in item %}
{% module Icon(item["icon"], classes="sidenav__link-icon") %}
{% end %}
<span class="sidenav__link-label">{{item["label"]}}</span>
</a>
</li>
{% end %}
</ul>
{% end %}
</li>

View File

@ -1,10 +1,24 @@
<div class="global-navigation sidenav global-navigation__context--{{context}}">
<ul>
{% if dev() %}
{% module SidenavItem("Styleguide", href="/styleguide", icon="visible", active=matchesPath('/styleguide')) %}
{% module SidenavItem("Styleguide",
href="/styleguide",
icon="visible",
active=matchesPath('/styleguide'),
subnav=[
{"label":"Subnav 1", "href":"/styleguide?subnav1", "icon": "plus", "active": matchesPath('/styleguide?subnav1')},
{"label":"Subnav 2", "href":"/styleguide?subnav2", "active": matchesPath('/styleguide?subnav2')},
]) %}
{% end %}
{% module SidenavItem("Requests", href="/requests", icon="document", active=matchesPath('/requests')) %}
{% module SidenavItem("Requests",
href="/requests",
icon="document",
active=matchesPath('/requests'),
subnav=[
{"label":"New Request", "href":"/requests/new", "icon": "plus", "active": matchesPath('/requests/new')},
]
) %}
{% module SidenavItem("Workspaces", href="/workspaces", icon="cloud", active=matchesPath('/workspaces')) %}
</ul>
</div>

View File

@ -11,7 +11,7 @@
</a>
<a href="/" class="topbar__link">
<span class="topbar__link-label">Sam Seeceepio</span>
<span class="topbar__link-label">{{ current_user["first_name"] + " " + current_user["last_name"] }}</span>
{% module Icon('avatar', classes='topbar__link-icon') %}
</a>
</div>

View File

@ -3,49 +3,63 @@
{% block content %}
{% module Alert('Pending Financial Verification',
message="<p>Your next step is to create a Task Order (T.O.) associated with JEDI Cloud. Please consult a Contracting Officer (KO) or Contracting Officer Representative (COR) to help with this step.</p>"
) %}
<div class="col col--grow">
<div class='panel'>
<div class='row'>
<div class='col col--grow col--pad'>
<form class="usa-search usa-search-small">
<label class="usa-sr-only" for="search-field-small">Search small</label>
<input id="search-field-small" type="search" name="search" placeholder="Search by Order ID">
<button type="submit">
<span class="usa-sr-only">Search</span>
</button>
</form>
</div>
<div class='col col--grow col--pad'>
<select id="filter_status" name="filter_status" required="">
<option value="" selected disabled>Filter by status</option>
<option value="">Active</option>
<option value="">Pending</option>
<option value="">Denied</option>
</select>
</div>
</div>
</div>
<div class="panel">
<div class="panel__content">
<div class="panel__heading">
<h1>Requests <a class="usa-button usa-button-secondary" href='{{ reverse_url('request_new') }}'>New Request</a></h1>
</div>
<table class="usa-table-borderless" width="100%">
<thead>
<tr>
<th scope="col">Order ID</th>
<th scope="col">Request Date</th>
<th scope="col">Requester</th>
<th scope="col">Total Apps</th>
<th scope="col">Status</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{% for r in requests %}
<tr>
<th scope="row"><a href="{{ reverse_url('request_form_update', 1, r['order_id']) }}">{{ r['order_id'] }}</a>
{% if r['is_new'] %}<span class="usa-label">New</span>
</th>
{% end %}
<td>{{ r['date'] }}</td>
<td>{{ r['full_name'] }}</td>
<td>{{ r['app_count'] }}</td>
<td>{{ r['status'] }}</td>
<td><a href="">Download</a></td>
</tr>
<table>
<thead>
<tr>
<th>Order ID</th>
<th>Request Date</th>
<th>Requester</th>
<th>Total Apps</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for r in requests %}
<tr>
<td><a href="{{ reverse_url('request_form_update', 1, r['order_id']) }}">{{ r['order_id'] }}</a>
{% if r['is_new'] %}<span class="usa-label">New</span>
</td>
{% end %}
</tbody>
</table>
</div>
<td>{{ r['date'] }}</td>
<td>{{ r['full_name'] }}</td>
<td>{{ r['app_count'] }}</td>
<td>{{ r['status'] }}</td>
<td><a href="">Download</a></td>
</tr>
{% end %}
</tbody>
</table>
</div>
</div>

View File

@ -1,5 +1,22 @@
{% extends "base.html.to" %}
{% block modal %}
{% if modalOpen() %}
{% apply modal %}
<h1>A modal dialog</h1>
<p>We count thirty Rebel ships, Lord Vader. But they're so small they're evading our turbo-lasers! We'll have to destroy them ship to ship. Get the crews to their fighters. Luke, let me know when you're going in. I'm on my way in now... Watch yourself! There's a lot of fire coming from the right side of that deflection tower. I'm on it. Squad leaders, we've picked up a new group of signals. Enemy fighters coming your way.</p>
<p>I hope the old man got that tractor beam out if commission, or this is going to be a real short trip. Okay, hit it! We're coming up on the sentry ships. Hold 'em off! Angle the deflector shields while I charge up the main guns! I can't believe he's gone. There wasn't anything you could have done. Come on, buddy, we're not out of this yet! You in, kid? Okay, stay sharp!</p>
<div class='action-group'>
<a href='/styleguide' class='action-group__action usa-button'>Close</a>
<a href='/styleguide' class='action-group__action'>This also closes the modal</a>
</div>
{% end %}
{% end %}
{% end %}
{% block content %}
{% module Alert('A Warning Alert',
@ -7,7 +24,7 @@
<p>This is a message. It is a very important message. Please note, <strong>proper semantic markup is required</strong> here, such as paragraph tags. Don't omit paragraph tags!</p>\
<p>Also note the same for actions below. You'll need to include the full link markup.</p>\
",
actions="<a href='/styleguide'>Do something</a>",
actions="<a href='/styleguide?modal=True'>Open a Modal Dialog</a>",
level='warning'
) %}
@ -191,5 +208,10 @@
</tr>
</tbody>
</table>
<div class='action-group'>
<a href='/styleguide' class='action-group__action usa-button usa-button-big'>Action Group Button</a>
<a href='/styleguide' class='action-group__action'>Action group link</a>
</div>
</div>
{% end %}