Merge pull request #233 from dod-ccpo/ui/ws-role-picker

UI/Selector Vue component
This commit is contained in:
andrewdds 2018-08-31 11:25:52 -04:00 committed by GitHub
commit 1c73c1a191
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 210 additions and 16 deletions

View File

@ -102,3 +102,31 @@ COMPLETION_DATE_RANGES = [
("3-6 months", "3-6 months"),
("Above 12 months", "Above 12 months"),
]
WORKSPACE_ROLES = [
(
"owner",
"Workspace Owner",
"Can add, edit, deactivate access to all projects, environments, and members. Can view budget reports. Can start and edit JEDI Cloud requests.",
),
(
"admin",
"Administrator",
"Can add and edit projects, environments, members, but cannot deactivate. Cannot view budget reports or JEDI Cloud requests.",
),
(
"developer",
"Developer",
"Can view only the projects and environments they are granted access to. Can also view members associated with each environment.",
),
(
"billing_auditor",
"Billing Auditor",
"Can view only the projects and environments they are granted access to. Can also view budgets and reports associated with the workspace.",
),
(
"security_auditor",
"Security Auditor",
"Can view only the projects and environments they are granted access to. Can also view activity logs.",
),
]

View File

@ -6,6 +6,8 @@ from wtforms.validators import Required, Email, Length
from atst.forms.validators import IsNumber
from atst.forms.fields import SelectField
from .data import WORKSPACE_ROLES
class NewMemberForm(Form):
@ -14,15 +16,5 @@ class NewMemberForm(Form):
email = EmailField("Email Address", validators=[Required(), Email()])
dod_id = StringField("DOD ID", validators=[Required(), Length(min=10), IsNumber()])
workspace_role = SelectField(
"Workspace Role",
choices=[
("", "Select a Role"),
("admin", "Admin"),
("billing_auditor", "Billing Auditor"),
("ccpo", "CCPO"),
("developer", "Developer"),
("owner", "Owner"),
("security_auditor", "Security Auditor"),
],
validators=[Required()],
"Workspace Role", choices=WORKSPACE_ROLES, validators=[Required()], default=""
)

44
js/components/selector.js Normal file
View File

@ -0,0 +1,44 @@
import { VPopover } from 'v-tooltip'
export default {
name: 'selector',
components: {
VPopover
},
props: {
choices: Array,
defaultLabel: String,
initialErrors: Array,
initialChoice: {
type: String,
default: null
}
},
data: function () {
return {
value: this.initialChoice || null,
showError: (this.initialErrors && this.initialErrors.length) || false
}
},
computed: {
label: function () {
return this.value
? this.choices.find((choice) => {
return this.value === choice[0]
})[1]
: this.defaultLabel
}
},
methods: {
change: function (e) {
this.value = e.target.value
this.showError = false
setTimeout(() => this.$refs.popover.hide(), 300)
}
},
}

View File

@ -13,6 +13,7 @@ import financial from './components/forms/financial'
import toggler from './components/toggler'
import NewProject from './components/forms/new_project'
import Modal from './mixins/modal'
import selector from './components/selector'
Vue.use(VTooltip)
@ -28,7 +29,8 @@ const app = new Vue({
DetailsOfUse,
poc,
financial,
NewProject
NewProject,
selector
},
mounted: function() {
const modalOpen = document.querySelector("#modalOpen")

View File

@ -33,6 +33,8 @@
@import 'components/progress_menu.scss';
@import 'components/search_bar';
@import 'components/forms';
@import 'components/selector';
@import 'sections/login';
@import 'sections/request_approval';

View File

@ -0,0 +1,54 @@
.selector {
max-width: 30em;
.trigger {
display: block !important;
}
legend {
@include h4;
padding-bottom: $gap / 2;
}
.selector__button {
width: 100%;
height: $input-height;
margin: 0;
padding: $input-padding-vertical 0.7em;
line-height: $input-line-height;
color: $color-base;
font-size: $base-font-size;
font-weight: $font-normal;
text-align: left;
border-width: 1px;
border-style: solid;
border-color: $color-gray;
border-radius: 0;
box-sizing: border-box;
background-color: $color-white;
background-image: none, url('#{$image-path}/arrow-both.svg'), url('#{$image-path}/arrow-both.png');
background-position: right 1.3rem center;
background-repeat: no-repeat;
background-size: 1rem;
}
.tooltip {
&.popover {
.popover-inner {
padding: 0;
.block-list {
margin: 0;
label {
padding: 0;
}
}
}
.popover-arrow {
background-color: $color-white;
}
}
}
}

View File

@ -106,6 +106,8 @@
justify-content: space-between;
&::before {
flex-shrink: 0;
margin-right: 0;
margin-left: $gap * 2;
}
&:hover {

View File

@ -37,7 +37,8 @@
input,
textarea,
select {
select,
.selector__button {
border-color: $state-color;
border-width: $border-width;
}
@ -72,6 +73,10 @@
position: relative;
clear: both;
dd {
font-weight: normal;
}
.icon-validation {
position: absolute;
top: 100%;
@ -105,7 +110,8 @@
input,
textarea,
select {
select,
.selector__button {
@include line-max;
margin: 0;
box-sizing: border-box;

View File

@ -68,7 +68,6 @@
background: $color;
color: black;
padding: 24px;
border-radius: 5px;
box-shadow: 0 5px 30px rgba(black, .1);
}

View File

@ -0,0 +1,64 @@
{% from "components/icon.html" import Icon %}
{# expects a wtforms SelectField instance #}
{% macro Selector(field, default_label='Select an option') -%}
<selector
v-bind:choices='{{ field.choices | tojson }}'
default-label='{{ default_label }}'
{% if field.data %}initial-choice='{{ field.data }}'{% endif %}
{% if field.errors %}v-bind:initial-errors='{{ field.errors }}'{% endif %}
inline-template>
<fieldset v-bind:class="['selector usa-input', { 'usa-input--error': initialErrors }]">
<v-popover v-bind:container='false' ref='popover'>
<legend>
{{ field.label | striptags }}
{% if field.description %}
<span class='usa-input__help'>{{ field.description | safe }}</span>
{% endif %}
<span v-show='showError'>{{ Icon('alert',classes="icon-validation") }}</span>
</legend>
<button class='selector__button' type='button' v-html='label'></button>
<span v-show='showError'>{{ Icon('alert',classes="icon-validation") }}</span>
<input type='hidden' name='{{ field.name }}' v-bind:value='value'/>
<template v-if='showError'>
<span v-if='initialErrors' v-for='error in initialErrors' class='usa-input__message' v-html='error'></span>
</template>
<template slot='popover'>
<div class='block-list'>
<ul>
<li v-for='choice in choices' class='block-list__item block-list__item--selectable'>
<template v-if='choice[0] !== ""'>
<input
type='radio'
v-bind:id="'{{ field.name }}_' + choice[0]"
v-bind:value='choice[0]'
v-bind:checked='value === choice[0]'
v-on:change='change'/>
<label v-bind:for="'{{ field.name }}_' + choice[0]">
<template v-if='choices[2]'>
<dl>
<dt v-html='choice[1]'></dt>
<dd v-html='choice[2]'></dd>
</dl>
</template>
<span v-else v-html='choice[1]'>
</label>
</template>
</li>
</ul>
</div>
</template>
</v-popover>
</fieldset>
</selector>
{%- endmacro %}

View File

@ -3,6 +3,7 @@
{% from "components/icon.html" import Icon %}
{% from "components/text_input.html" import TextInput %}
{% from "components/options_input.html" import OptionsInput %}
{% from "components/selector.html" import Selector %}
{% block content %}
@ -20,7 +21,7 @@
{{ TextInput(form.last_name) }}
{{ TextInput(form.email,placeholder='jane@mail.mil', validation='email') }}
{{ TextInput(form.dod_id,placeholder='10-digit number on the back of the CAC', validation='dodId') }}
{{ OptionsInput(form.workspace_role) }}
{{ Selector(form.workspace_role) }}
</div>
</div>