diff --git a/atst/forms/data.py b/atst/forms/data.py index fba93d84..6a41c647 100644 --- a/atst/forms/data.py +++ b/atst/forms/data.py @@ -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.", + ), +] diff --git a/atst/forms/new_member.py b/atst/forms/new_member.py index 90bd1b1c..49834d9f 100644 --- a/atst/forms/new_member.py +++ b/atst/forms/new_member.py @@ -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="" ) diff --git a/js/components/selector.js b/js/components/selector.js new file mode 100644 index 00000000..b6c23023 --- /dev/null +++ b/js/components/selector.js @@ -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) + } + }, +} diff --git a/js/index.js b/js/index.js index b89505d2..2ce01476 100644 --- a/js/index.js +++ b/js/index.js @@ -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") diff --git a/styles/atat.scss b/styles/atat.scss index 1b7b65fd..3d70a544 100644 --- a/styles/atat.scss +++ b/styles/atat.scss @@ -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'; diff --git a/styles/components/_selector.scss b/styles/components/_selector.scss new file mode 100644 index 00000000..7b95b325 --- /dev/null +++ b/styles/components/_selector.scss @@ -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; + } + } + } +} diff --git a/styles/elements/_block_lists.scss b/styles/elements/_block_lists.scss index 1da1c14d..a0f3071a 100644 --- a/styles/elements/_block_lists.scss +++ b/styles/elements/_block_lists.scss @@ -106,6 +106,8 @@ justify-content: space-between; &::before { flex-shrink: 0; + margin-right: 0; + margin-left: $gap * 2; } &:hover { diff --git a/styles/elements/_inputs.scss b/styles/elements/_inputs.scss index 53fb9d9f..e3f49aac 100644 --- a/styles/elements/_inputs.scss +++ b/styles/elements/_inputs.scss @@ -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; diff --git a/styles/elements/_tooltip.scss b/styles/elements/_tooltip.scss index 44876171..d444826f 100644 --- a/styles/elements/_tooltip.scss +++ b/styles/elements/_tooltip.scss @@ -68,7 +68,6 @@ background: $color; color: black; padding: 24px; - border-radius: 5px; box-shadow: 0 5px 30px rgba(black, .1); } diff --git a/templates/components/selector.html b/templates/components/selector.html new file mode 100644 index 00000000..cfa44d0a --- /dev/null +++ b/templates/components/selector.html @@ -0,0 +1,64 @@ +{% from "components/icon.html" import Icon %} + +{# expects a wtforms SelectField instance #} +{% macro Selector(field, default_label='Select an option') -%} + + + +
+ + + {{ field.label | striptags }} + + {% if field.description %} + {{ field.description | safe }} + {% endif %} + + {{ Icon('alert',classes="icon-validation") }} + + + + + {{ Icon('alert',classes="icon-validation") }} + + + + + + + +
+
+ +{%- endmacro %} diff --git a/templates/member_new.html b/templates/member_new.html index ad3723bf..a1819bed 100644 --- a/templates/member_new.html +++ b/templates/member_new.html @@ -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) }}