From 22ef8f432c48512da4929716a482922c54922036 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 24 Jul 2018 16:48:15 -0400 Subject: [PATCH 001/173] Create mock eda client --- atst/eda_client.py | 356 +++++++++++++++++++++++++++++++++++++++ tests/test_eda_client.py | 17 ++ 2 files changed, 373 insertions(+) create mode 100644 atst/eda_client.py create mode 100644 tests/test_eda_client.py diff --git a/atst/eda_client.py b/atst/eda_client.py new file mode 100644 index 00000000..09acd859 --- /dev/null +++ b/atst/eda_client.py @@ -0,0 +1,356 @@ +class EDAClientBase(object): + def list_contracts( + self, + contract_number=None, + delivery_order=None, + cage_code=None, + duns_number=None, + ): + """ + Get a list of all contracts matching the given filters. + """ + raise NotImplementedError() + + def get_contract(self, contract_number, status): + """ + Get details for a contract. + """ + raise NotImplementedError() + + +class MockEDAClient(EDAClientBase): + def __init__(self, *args, **kwargs): + pass + + def list_contracts( + self, + contract_number=None, + delivery_order=None, + cage_code=None, + duns_number=None, + ): + return [ + { + "aco_mod": "01", + "admin_dodaac": None, + "cage_code": "1U305", + "contract_no": "DCA10096D0052", + "delivery_order": "0084", + "duns_number": None, + "issue_date": "20000228", + "issue_dodaac": None, + "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=", + "pay_dodaac": None, + "pco_mod": "02", + }, + { + "aco_mod": "01", + "admin_dodaac": None, + "cage_code": "1U305", + "contract_no": "DCA10096D0052", + "delivery_order": "0084", + "duns_number": None, + "issue_date": "20000228", + "issue_dodaac": None, + "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=", + "pay_dodaac": None, + "pco_mod": "02", + }, + { + "aco_mod": "01", + "admin_dodaac": None, + "cage_code": "1U305", + "contract_no": "DCA10096D0052", + "delivery_order": "0084", + "duns_number": None, + "issue_date": "20000228", + "issue_dodaac": None, + "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=", + "pay_dodaac": None, + "pco_mod": "02", + }, + ] + + def get_contract(self, contract_number, status): + if contract_number == "DCA10096D0052" and status == "y": + return { + "aco_mod": "01", + "admin_dodaac": None, + "cage_code": "1U305", + "contract_no": "DCA10096D0052", + "delivery_order": "0084", + "duns_number": None, + "issue_date": "20000228", + "issue_dodaac": None, + "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=", + "pay_dodaac": None, + "pco_mod": "02", + "amount": 2000000 + } + else: + return None + + +class EDAClient(EDAClientBase): + def __init__(self, base_url, user_name, user_role): + pass + + def list_contracts( + self, + contract_number=None, + delivery_order=None, + cage_code=None, + duns_number=None, + ): + # TODO: Fetch the contracts CSV and transform them into dictionaries. + # https://docs.python.org/3/library/csv.html#csv.DictReader + raise NotImplementedError() + + def get_contract(self, contract_number, status): + # TODO: Fetch the contract XML and transform it into a dictionary. + # https://docs.python.org/3.7/library/xml.etree.elementtree.html + raise NotImplementedError() + + + +CONTRACT_XML = """ + +2.5 +DD 1155 + +3244871 + +00000431 +704331 + + + + + +Department of Defense +Delivery Order +70433119F2644 +Represented Contract + + +Department of Defense +Basic Ordering Agreement +W81K0419G0001 +Ordering Instrument + + +false +Original +false + +Firm Fixed Price + + + + +http://farsite.hill.af.mil/reghtml/regs/far2afmcfars/fardfars/far/52_220.htm#P810_149596 + + +FAR +52.222-50 +Combating Trafficking in Persons. +2015-05 + + + [ lots of text ] + + +
I
+
+ +FAR +52.245-1 +Government Property. +2012-04 + + + [ lots of text ] + + +
I
+
+
+ +2016-02-04 + +2016-01-25 + +DALE WOLFE + +Telephone +520-533-9132 + + + + + +Contractor +
+ +0Z7K0 +808152482 + + +CACI TECHNOLOGIES, INC + + +6933 Gateway Ct +Manassas VA, 20109 + + + +
+
+ +Contract Issuing Office +
+ +704331 + + +FEMA DISTRIBUTION CENTER + + +3870 S. SIDE INDUSTRIAL CTR +ATLANTA GA, 30354 + + + +
+ +GENE BARBER + +Telephone +(202) 646-2727 + + +
+ +Contract Administrative Office +
+ +704331 + + +FEMA DISTRIBUTION CENTER + + +3870 S. SIDE INDUSTRIAL CTR +ATLANTA GA, 30354 + + + +
+
+ +Paying Office +
+ +HQ0131 + + +DEFENSE FINANCE AND ACCOUNTING SVC + + +P.O. BOX 369016 +COLUMBUS OH, 43236 + + + +
+
+ +Ship To +
+ +S0302A + + +DCMA PHOENIX + + +40 NORTH CENTRAL AVE, STE 400 +TWO RENAISSANCE SQUARE +PHOENIX AZ, 85004 + + + +
+
+ + +Header Only - Total Contract Value +192000.00 + + + + +Delivery Requested By + +2016-01-16 + + + + + +Defense Priorities Allocation System (DPAS) Priority Rating + +DO-A7 +
A
+
+ + +Contractor +Origin (after Loading) + + +
+ + + + + +CLIN +0001 + + + + +false + +Cost No Fee + + +Real Property +Radio Dishes +3 +false +Estimated +Each +64000.00 + +Manufacturer's Part Number +5L33M7730291DX081 + + + + + +Estimated Cost +192000.00 + + +Not to Exceed Amount (Funding) +200000.00 + + + + +
+
+""" diff --git a/tests/test_eda_client.py b/tests/test_eda_client.py new file mode 100644 index 00000000..eb1e92d8 --- /dev/null +++ b/tests/test_eda_client.py @@ -0,0 +1,17 @@ +from atst.eda_client import MockEDAClient + + +client = MockEDAClient() + +def test_list_contracts(): + results = client.list_contracts() + assert len(results) == 3 + +def test_get_contract(): + result = client.get_contract("DCA10096D0052", "y") + assert result["contract_no"] == "DCA10096D0052" + assert result["amount"] == 2000000 + +def test_contract_not_found(): + result = client.get_contract("abc", "y") + assert result is None From 1823e45291d0f8a5cb9da19791a79b1fb57765c1 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Tue, 31 Jul 2018 10:00:27 -0400 Subject: [PATCH 002/173] Clean up workspace list layout --- templates/workspaces.html.to | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/templates/workspaces.html.to b/templates/workspaces.html.to index 6e7e7931..21bbad7d 100644 --- a/templates/workspaces.html.to +++ b/templates/workspaces.html.to @@ -5,22 +5,23 @@ - - - + + + {% for w in workspaces %} - + - {% end %} From a7f49d1299a974d276dc96d600e3edd7e5703467 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 30 Jul 2018 16:09:55 -0400 Subject: [PATCH 003/173] EmptyState UI module --- atst/ui_modules.py | 9 ++++++ scss/components/_empty_state.scss | 36 ++++++++++++++++-------- templates/components/empty_state.html.to | 9 ++++++ 3 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 templates/components/empty_state.html.to diff --git a/atst/ui_modules.py b/atst/ui_modules.py index 748ca980..96bdab07 100644 --- a/atst/ui_modules.py +++ b/atst/ui_modules.py @@ -46,3 +46,12 @@ class SidenavItem(UIModule): active=active, icon=icon, subnav=subnav) + +class EmptyState(UIModule): + def render(self, message, actionLabel, actionHref, icon=None): + return self.render_string( + "components/empty_state.html.to", + message=message, + actionLabel=actionLabel, + actionHref=actionHref, + icon=icon) diff --git a/scss/components/_empty_state.scss b/scss/components/_empty_state.scss index d11f5083..be8675ad 100644 --- a/scss/components/_empty_state.scss +++ b/scss/components/_empty_state.scss @@ -1,15 +1,27 @@ .empty-state { text-align: center; - padding-top: 10rem; - - p { - font-family: $font-sans; - font-weight: 300; - line-height: 10rem; - font-size: 44px; - line-height: 5rem; - margin: 0 auto; - padding-bottom: 2rem; - max-width: 40%; + padding: 6rem ($gap * 2) 0; + display: flex; + flex-direction: column; + align-items: center; + + @include media($medium-screen) { + padding: 8rem ($gap * 4) 0; } -} \ No newline at end of file + + .icon { + @include icon-size(50); + @include icon-color($color-gray-light); + } + + p { + @include h2; + line-height: 1.2; + max-width: 15em; + color: $color-gray; + + @include media($large-screen) { + @include h1; + } + } +} diff --git a/templates/components/empty_state.html.to b/templates/components/empty_state.html.to new file mode 100644 index 00000000..30246ddb --- /dev/null +++ b/templates/components/empty_state.html.to @@ -0,0 +1,9 @@ +
+

{{ message }}

+ + {% if icon %} + {% module Icon(icon) %} + {% end %} + + {{ actionLabel }} +
From d9d638ab3b7fec632b415bac06e3bec58aac01a8 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 30 Jul 2018 16:10:28 -0400 Subject: [PATCH 004/173] Add conditional empty state modules to Requests, Workspace Members, and Workspace Projects --- templates/requests.html.to | 124 +++++++++++++++------------ templates/workspace_members.html.to | 118 +++++++++++-------------- templates/workspace_projects.html.to | 65 ++++++++------ 3 files changed, 163 insertions(+), 144 deletions(-) diff --git a/templates/requests.html.to b/templates/requests.html.to index 66dbcd9d..1cdd2433 100644 --- a/templates/requests.html.to +++ b/templates/requests.html.to @@ -1,5 +1,9 @@ {% extends "base.html.to" %} +{% block template_vars %} + {% set requestsEmpty = False %} +{% end %} + {% block modal %} {% if modalOpen() %} {% apply modal %} @@ -31,67 +35,79 @@ {% block content %} +{% if requestsEmpty %} -{% module Alert('Pending Financial Verification', - message="

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.

" -) %} + {% module EmptyState( + 'There are currently no active requests for you to see.', + actionLabel='Create a new JEDI Cloud Request', + actionHref='/requests/new', + icon='document' + )%} -
+{% else %} - -
- - - -
+ {% module Alert('Pending Financial Verification', + message="

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.

" + ) %} -
- - -
- +
-
-
Workspace NameWorkspace InfoActionsWorkspace NameTask OrderUsers
- {{ w['name'] }}
- Task Order: #{{ w['task_order']['number'] }} +
+ {{ w['name'] }}
- {{ w['user_count'] }}
Users + #{{ w['task_order']['number'] }} +
+ {{ w['user_count'] }}Users
- - - - - - - - - - - - {% for r in requests %} - - + +
+ + + +
+ +
+ + +
+ + +
+
Order IDRequest DateRequesterTotal AppsStatusActions
- {{ r['order_id'] }} - {% if r['is_new'] %}New -
+ + + + + + + + + + + + {% for r in requests %} + + + {% end %} + + + + + + {% end %} - - - - - - - {% end %} - -
Order IDRequest DateRequesterTotal AppsStatusActions
+ {{ r['order_id'] }} + {% if r['is_new'] %}New + {{ r['date'] }}{{ r['full_name'] }}{{ r['app_count'] }}{{ r['status'] }} + Download + Approval +
{{ r['date'] }}{{ r['full_name'] }}{{ r['app_count'] }}{{ r['status'] }} - Download - Approval -
+ + + - + +{% end %} {% end %} diff --git a/templates/workspace_members.html.to b/templates/workspace_members.html.to index a27a0b0b..53e70385 100644 --- a/templates/workspace_members.html.to +++ b/templates/workspace_members.html.to @@ -1,92 +1,78 @@ {% extends "base_workspace.html.to" %} +{% block template_vars %} + {% set membersEmpty = False %} +{% end %} + {% block workspace_content %} +{% if membersEmpty %} - +{% else %} -{#
-
-
- + + + +
+ + + + + + + + + + + {% for m in members %} + + + + + + + {% end %} + +
Name Status FlagStatusWorkspace Role
{{ m['first_name'] }} {{ m['last_name'] }}{% if m['num_projects'] == '0' %} No Project Access {% end %}{{ m['status'] }}{{ m['workspace_role'] }}
-
#} - - -
- - - - - - - - - - - {% for m in members %} - - - - - - - {% end %} - -
Name Status FlagStatusWorkspace Role
{{ m['first_name'] }} {{ m['last_name'] }}{% if m['num_projects'] == '0' %} No Project Access {% end %}{{ m['status'] }}{{ m['workspace_role'] }}
-
+{% end %} {% end %} diff --git a/templates/workspace_projects.html.to b/templates/workspace_projects.html.to index e4008c3c..620b8396 100644 --- a/templates/workspace_projects.html.to +++ b/templates/workspace_projects.html.to @@ -1,32 +1,49 @@ {% extends "base_workspace.html.to" %} +{% block template_vars %} + {% set projectsEmpty = False %} +{% end %} + {% block workspace_content %} -{% for project in projects %} -
-
-

{{ project['name'] }} ({{ len(project['environments'])}} environments)

- - {% module Icon('edit') %} - edit - -
- -
{% end %} {% end %} From 4331f54adb670e805e088cf33b2b8eef11176d10 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Tue, 31 Jul 2018 12:07:25 -0400 Subject: [PATCH 005/173] remove dummy "empty" vars, just check if the arrays are empty --- templates/requests.html.to | 6 +----- templates/workspace_members.html.to | 6 +----- templates/workspace_projects.html.to | 6 +----- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/templates/requests.html.to b/templates/requests.html.to index 1cdd2433..bd0c9e8c 100644 --- a/templates/requests.html.to +++ b/templates/requests.html.to @@ -1,9 +1,5 @@ {% extends "base.html.to" %} -{% block template_vars %} - {% set requestsEmpty = False %} -{% end %} - {% block modal %} {% if modalOpen() %} {% apply modal %} @@ -35,7 +31,7 @@ {% block content %} -{% if requestsEmpty %} +{% if not requests %} {% module EmptyState( 'There are currently no active requests for you to see.', diff --git a/templates/workspace_members.html.to b/templates/workspace_members.html.to index 53e70385..074628da 100644 --- a/templates/workspace_members.html.to +++ b/templates/workspace_members.html.to @@ -1,12 +1,8 @@ {% extends "base_workspace.html.to" %} -{% block template_vars %} - {% set membersEmpty = False %} -{% end %} - {% block workspace_content %} -{% if membersEmpty %} +{% if not members %} {% module EmptyState( 'There are currently no members in this Workspace.', diff --git a/templates/workspace_projects.html.to b/templates/workspace_projects.html.to index 620b8396..34b0933b 100644 --- a/templates/workspace_projects.html.to +++ b/templates/workspace_projects.html.to @@ -1,12 +1,8 @@ {% extends "base_workspace.html.to" %} -{% block template_vars %} - {% set projectsEmpty = False %} -{% end %} - {% block workspace_content %} -{% if projectsEmpty %} +{% if not projects %} {% module EmptyState( 'There are currently no projects set up for this Workspace.', From 905375d79c0675c3a65b8d2f5be0b591e703b0e8 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 31 Jul 2018 14:44:09 -0400 Subject: [PATCH 006/173] Remove unnecessary XML --- atst/eda_client.py | 244 --------------------------------------------- 1 file changed, 244 deletions(-) diff --git a/atst/eda_client.py b/atst/eda_client.py index 09acd859..cebaad27 100644 --- a/atst/eda_client.py +++ b/atst/eda_client.py @@ -110,247 +110,3 @@ class EDAClient(EDAClientBase): # TODO: Fetch the contract XML and transform it into a dictionary. # https://docs.python.org/3.7/library/xml.etree.elementtree.html raise NotImplementedError() - - - -CONTRACT_XML = """ - -2.5 -DD 1155 - -3244871 - -00000431 -704331 - - - - - -Department of Defense -Delivery Order -70433119F2644 -Represented Contract - - -Department of Defense -Basic Ordering Agreement -W81K0419G0001 -Ordering Instrument - - -false -Original -false - -Firm Fixed Price - - - - -http://farsite.hill.af.mil/reghtml/regs/far2afmcfars/fardfars/far/52_220.htm#P810_149596 - - -FAR -52.222-50 -Combating Trafficking in Persons. -2015-05 - - - [ lots of text ] - - -
I
-
- -FAR -52.245-1 -Government Property. -2012-04 - - - [ lots of text ] - - -
I
-
-
- -2016-02-04 - -2016-01-25 - -DALE WOLFE - -Telephone -520-533-9132 - - - - - -Contractor -
- -0Z7K0 -808152482 - - -CACI TECHNOLOGIES, INC - - -6933 Gateway Ct -Manassas VA, 20109 - - - -
-
- -Contract Issuing Office -
- -704331 - - -FEMA DISTRIBUTION CENTER - - -3870 S. SIDE INDUSTRIAL CTR -ATLANTA GA, 30354 - - - -
- -GENE BARBER - -Telephone -(202) 646-2727 - - -
- -Contract Administrative Office -
- -704331 - - -FEMA DISTRIBUTION CENTER - - -3870 S. SIDE INDUSTRIAL CTR -ATLANTA GA, 30354 - - - -
-
- -Paying Office -
- -HQ0131 - - -DEFENSE FINANCE AND ACCOUNTING SVC - - -P.O. BOX 369016 -COLUMBUS OH, 43236 - - - -
-
- -Ship To -
- -S0302A - - -DCMA PHOENIX - - -40 NORTH CENTRAL AVE, STE 400 -TWO RENAISSANCE SQUARE -PHOENIX AZ, 85004 - - - -
-
- - -Header Only - Total Contract Value -192000.00 - - - - -Delivery Requested By - -2016-01-16 - - - - - -Defense Priorities Allocation System (DPAS) Priority Rating - -DO-A7 -
A
-
- - -Contractor -Origin (after Loading) - - -
- - - - - -CLIN -0001 - - - - -false - -Cost No Fee - - -Real Property -Radio Dishes -3 -false -Estimated -Each -64000.00 - -Manufacturer's Part Number -5L33M7730291DX081 - - - - - -Estimated Cost -192000.00 - - -Not to Exceed Amount (Funding) -200000.00 - - - - -
-
-""" From 44b715fc012bc37d93f4f85bf3289e8580ae5d76 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 31 Jul 2018 15:16:04 -0400 Subject: [PATCH 007/173] Allow for multiple date formats --- atst/forms/fields.py | 12 +++++++++++- tests/forms/test_fields.py | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/forms/test_fields.py diff --git a/atst/forms/fields.py b/atst/forms/fields.py index 3e9de703..6f733bd1 100644 --- a/atst/forms/fields.py +++ b/atst/forms/fields.py @@ -7,7 +7,17 @@ import pendulum class DateField(DateField): def _value(self): if self.data: - return pendulum.parse(self.data).date() + date_formats = [ + "YYYY-MM-DD", + "MM/DD/YYYY" + ] + for _format in date_formats: + try: + return pendulum.from_format(self.data, _format).date() + except (ValueError, pendulum.parsing.exceptions.ParserError): + pass + + raise ValueError("Unable to parse string {}".format(self.data)) else: return None diff --git a/tests/forms/test_fields.py b/tests/forms/test_fields.py new file mode 100644 index 00000000..ceece7c5 --- /dev/null +++ b/tests/forms/test_fields.py @@ -0,0 +1,25 @@ +import pytest +from wtforms import Form +import pendulum + +from atst.forms.fields import DateField + + +class MyForm(Form): + date = DateField() + + +def test_date_ie_format(): + form = MyForm(data={"date": "12/24/2018"}) + assert form.date._value() == pendulum.date(2018, 12, 24) + + +def test_date_sane_format(): + form = MyForm(data={"date": "2018-12-24"}) + assert form.date._value() == pendulum.date(2018, 12, 24) + + +def test_date_insane_format(): + form = MyForm(data={"date": "hello"}) + with pytest.raises(ValueError): + form.date._value() From 9f5b945270a092c73ce1c4290375dabb9a69be7e Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Mon, 30 Jul 2018 17:26:07 -0400 Subject: [PATCH 008/173] Add member placeholder info --- atst/app.py | 1 + templates/member_edit.html.to | 85 +++++++++++++++++++ .../navigation/workspace_navigation.html.to | 15 +++- templates/workspace_members.html.to | 2 +- 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 templates/member_edit.html.to diff --git a/atst/app.py b/atst/app.py index 8b812018..aa101838 100644 --- a/atst/app.py +++ b/atst/app.py @@ -123,6 +123,7 @@ def make_app(config, deps, **kwargs): url(r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members"), url(r"/workspaces/(\S+)/projects", Workspace, {}, name="workspace_projects"), url(r"/workspaces/123456/projects/789/edit", Main, {"page": "project_edit"}, name="project_edit"), + url(r"/workspaces/123456/members/789/edit", Main, {"page": "member_edit"}, name="member_edit"), ] if not ENV == "production": diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to new file mode 100644 index 00000000..d454152c --- /dev/null +++ b/templates/member_edit.html.to @@ -0,0 +1,85 @@ +{% extends "base_workspace.html.to" %} + +{% block template_vars %} +{% set is_new_member = False %} +{% set member_name = "Danny Knight" %} +{% set member_email = "knight@mil.gov" %} +{% set member_workspace_role = "Billing Auditor" %} +{% set member_id = "789" %} +{% end %} + +{% block workspace_content %} + +{% module Alert( + "UI Mock", + message="

Please note, this screen is a non-functional UI mockup.

", + level="info" + ) %} + + +
+
+

+ {% if is_new_member %} + Add new member + {% else %} + {{ member_name }} + {% end %} +

+
Workspace Role {{member_workspace_role}}
+
+
+ + +
+
+
+ +
+
+
+ +
+
+

Code.mil

+ revoke all access +
+
    +
  • + + Development + +
    + no accessset role +
    +
  • +
  • + + Production + +
    + Billingset role +
    +
  • + +
+
+ + + + {% end %} + diff --git a/templates/navigation/workspace_navigation.html.to b/templates/navigation/workspace_navigation.html.to index 21b48bb5..65a9525b 100644 --- a/templates/navigation/workspace_navigation.html.to +++ b/templates/navigation/workspace_navigation.html.to @@ -17,7 +17,20 @@ {% module SidenavItem( "Members", href=reverse_url('workspace_members', '123456'), - active=matchesPath('\/workspaces\/[A-Za-z0-9]*\/members') + active=matchesPath('\/workspaces\/[A-Za-z0-9]*\/members'), + subnav=[ + { + "label": "Add New Member", + "href": "", + "active": matchesPath('/workspaces/members/new'), + "icon": "plus" + }, + { + "label": "Editing Member", + "href": "", + "active": matchesPath('/workspaces/123456/members/789/edit') + } + ] )%} {% module SidenavItem( diff --git a/templates/workspace_members.html.to b/templates/workspace_members.html.to index 074628da..0f538b05 100644 --- a/templates/workspace_members.html.to +++ b/templates/workspace_members.html.to @@ -58,7 +58,7 @@ {% for m in members %} - {{ m['first_name'] }} {{ m['last_name'] }} + {{ m['first_name'] }} {{ m['last_name'] }} {% if m['num_projects'] == '0' %} No Project Access {% end %} {{ m['status'] }} {{ m['workspace_role'] }} From b917b4bdb5c136e4877403312584ed54e597e878 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 10:29:22 -0400 Subject: [PATCH 009/173] Style block list links --- scss/elements/_block_lists.scss | 19 +++++++-- scss/elements/_icon_link.scss | 4 ++ templates/member_edit.html.to | 4 +- templates/workspace_projects.html.to | 61 +++++++++++----------------- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/scss/elements/_block_lists.scss b/scss/elements/_block_lists.scss index e7caed75..ac15f80d 100644 --- a/scss/elements/_block_lists.scss +++ b/scss/elements/_block_lists.scss @@ -54,14 +54,25 @@ .block-list { @include block-list; + + .icon-link { + margin: -$gap 0; + } + + .icon-link { + &:first-child { + margin-left: -$gap; + } + + &:last-child { + margin-right: -$gap; + } + + } } .block-list__header { @include block-list-header; - - .block-list__header__link { - @include icon-link; - } } .block-list__title { diff --git a/scss/elements/_icon_link.scss b/scss/elements/_icon_link.scss index 95e372ec..00daae3f 100644 --- a/scss/elements/_icon_link.scss +++ b/scss/elements/_icon_link.scss @@ -59,4 +59,8 @@ &.icon-link--large { @include icon-link-large; } + + &.icon-link--danger { + @include icon-link-color($color-red, $color-red-lightest); + } } diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index d454152c..e6f36673 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -48,7 +48,7 @@

Code.mil

- revoke all access + revoke all access
  • @@ -56,7 +56,7 @@ Development
    - no accessset role + no access set role
  • diff --git a/templates/workspace_projects.html.to b/templates/workspace_projects.html.to index 34b0933b..a9f1a8aa 100644 --- a/templates/workspace_projects.html.to +++ b/templates/workspace_projects.html.to @@ -2,44 +2,31 @@ {% block workspace_content %} -{% if not projects %} - - {% module EmptyState( - 'There are currently no projects set up for this Workspace.', - actionLabel='Create a new Project', - actionHref='/project/new', - icon='cloud' - )%} - -{% else %} - - {% for project in projects %} -
    -
    -

    {{ project['name'] }} ({{ len(project['environments'])}} environments)

    - - {% module Icon('edit') %} - edit - -
    - -
    - {% end %} +{% for project in projects %} +
    +
    +

    {{ project['name'] }} ({{ len(project['environments'])}} environments)

    + + {% module Icon('edit') %} + edit + +
    + +
    {% end %} {% end %} From e8ca86f34435e14ec5e7a27022fdb0c49e6a6c6e Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 10:42:14 -0400 Subject: [PATCH 010/173] Add placeholder project item --- templates/member_edit.html.to | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index e6f36673..ebd3416a 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -48,7 +48,7 @@

    Code.mil

    - revoke all access + revoke all access
  • -
+
+
+

Digital Dojo

+ no access +
+
+ +
  • + + Sandbox + +
    + no accessset role +
    +
  • Production From a4c4dc5ade8048b5b1ab91a9fb2a2350d0c362d2 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 13:49:06 -0400 Subject: [PATCH 013/173] Add fields to header --- templates/member_edit.html.to | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 44b9be53..89031d6b 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -18,17 +18,19 @@
    -

    - {% if is_new_member %} - Add new member - {% else %} - {{ member_name }} - {% end %} -

    +

    {{ member_name }}

    Workspace Role {{member_workspace_role}}
    - DOD ID: {{ member_id }} -
    Email: {{ member_email }}
    - edit account details +
    + +
    DOD ID:
    +
    {{ member_id }}
    +
    + +
    Email:
    +
    {{ member_email }}
    +
    +
    + edit account details
    From a47675d6e79a430ffeeda05f506deb3ccbb00473 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 14:17:14 -0400 Subject: [PATCH 014/173] Update search bar --- templates/member_edit.html.to | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 89031d6b..f7082b73 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -29,29 +29,24 @@
    Email:
    {{ member_email }}
    + edit account details - edit account details
  • - -
    -
    -
    - -
    +
    +
    -

    Code.mil

    +

    ▾ Code.mil

    revoke all access
      @@ -84,7 +79,7 @@
      -

      Digital Dojo

      +

      ▸ Digital Dojo

      no access
      From b0a79e9b388e18ee2c420dd8debbeec87309a523 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 14:27:33 -0400 Subject: [PATCH 015/173] Remove dl markup --- templates/member_edit.html.to | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index f7082b73..f9125323 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -20,17 +20,12 @@

      {{ member_name }}

      Workspace Role {{member_workspace_role}}
      -
      - -
      DOD ID:
      -
      {{ member_id }}
      -
      - -
      Email:
      -
      {{ member_email }}
      -
      - edit account details -
      + + DOD ID: + {{ member_id }} + Email: + {{ member_email }} + edit account details
    From 38a678422204bc97e4c27a9659a073492f02b962 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 14:44:56 -0400 Subject: [PATCH 016/173] Replace ascii traingles with svgs --- static/icons/arrow-down.svg | 1 + static/icons/arrow-right.svg | 1 + templates/member_edit.html.to | 4 ++-- templates/styleguide.html.to | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 static/icons/arrow-down.svg create mode 100644 static/icons/arrow-right.svg diff --git a/static/icons/arrow-down.svg b/static/icons/arrow-down.svg new file mode 100644 index 00000000..ec8fe0b9 --- /dev/null +++ b/static/icons/arrow-down.svg @@ -0,0 +1 @@ + diff --git a/static/icons/arrow-right.svg b/static/icons/arrow-right.svg new file mode 100644 index 00000000..524470fd --- /dev/null +++ b/static/icons/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index f9125323..3b744ad6 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -41,7 +41,7 @@
    -

    ▾ Code.mil

    +

    {% module Icon('arrow-down') %} Code.mil

    revoke all access
      @@ -74,7 +74,7 @@
      -

      ▸ Digital Dojo

      +

      {% module Icon('arrow-right') %} Digital Dojo

      no access
      diff --git a/templates/styleguide.html.to b/templates/styleguide.html.to index e90aefc9..1db19496 100644 --- a/templates/styleguide.html.to +++ b/templates/styleguide.html.to @@ -301,6 +301,8 @@ {% module Icon('link') %} 'link'    {% module Icon('ok') %} 'ok'    {% module Icon('checkmark') %} 'checkmark'    + {% module Icon('arrow-right') %} 'arrow-right'    + {% module Icon('arrow-down') %} 'arrow-down'   
    From fbfd0b6c8c73dac6517668d614bc391d1612c8b8 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 16:04:17 -0400 Subject: [PATCH 017/173] Update member header layout --- scss/atat.scss | 1 + scss/sections/_member_edit.scss | 37 +++++++++++++++++++++++++++++++++ templates/member_edit.html.to | 27 +++++++++++++++--------- 3 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 scss/sections/_member_edit.scss diff --git a/scss/atat.scss b/scss/atat.scss index f9e7f6aa..b4ae7797 100644 --- a/scss/atat.scss +++ b/scss/atat.scss @@ -33,3 +33,4 @@ @import 'sections/request_approval'; @import 'sections/projects_list'; @import 'sections/project_edit'; +@import 'sections/member_edit'; diff --git a/scss/sections/_member_edit.scss b/scss/sections/_member_edit.scss new file mode 100644 index 00000000..c868137a --- /dev/null +++ b/scss/sections/_member_edit.scss @@ -0,0 +1,37 @@ +.member-card { + @include grid-row; + padding: $gap*2; + justify-content: space-between; + + dl { + margin: 0; + + > div { + margin-bottom: $gap; + } + } + + dt { + font-weight: normal; + color: $color-gray; + } + + dd { + display: inline; + } + + .member-card__header { + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .member-card__heading { + margin: 0; + @include h2; + } + + .member-card__details { + text-align: right; + } +} \ No newline at end of file diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 3b744ad6..140e8a26 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -16,16 +16,23 @@ level="info" ) %} -
    -
    -

    {{ member_name }}

    -
    Workspace Role {{member_workspace_role}}
    - - DOD ID: - {{ member_id }} - Email: - {{ member_email }} - edit account details +
    +
    +

    {{ member_name }}

    +
    Workspace Role
    {{member_workspace_role}}
    +
    +
    +
    +
    +
    DOD ID:
    +
    {{ member_id }}
    +
    +
    +
    Email:
    +
    {{ member_email }}
    +
    +
    + edit account details
    From 546ecef08fc43adc9323feb285ab654141298227 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Tue, 31 Jul 2018 16:16:43 -0400 Subject: [PATCH 018/173] Style lables and adjust list --- scss/elements/_block_lists.scss | 3 ++- scss/elements/_typography.scss | 8 ++------ scss/sections/_member_edit.scss | 4 ++++ templates/member_edit.html.to | 10 +++++----- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/scss/elements/_block_lists.scss b/scss/elements/_block_lists.scss index ac15f80d..6cb24d11 100644 --- a/scss/elements/_block_lists.scss +++ b/scss/elements/_block_lists.scss @@ -59,7 +59,8 @@ margin: -$gap 0; } - .icon-link { + .icon-link, + .label { &:first-child { margin-left: -$gap; } diff --git a/scss/elements/_typography.scss b/scss/elements/_typography.scss index 10f0846a..fcdc97d9 100644 --- a/scss/elements/_typography.scss +++ b/scss/elements/_typography.scss @@ -4,7 +4,7 @@ * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_typography.scss */ -* { + * { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -56,8 +56,4 @@ dl { > div { margin-bottom: $gap * 2; } -} - -.subtitle { - color: $color-gray; -} +} \ No newline at end of file diff --git a/scss/sections/_member_edit.scss b/scss/sections/_member_edit.scss index c868137a..aef2e042 100644 --- a/scss/sections/_member_edit.scss +++ b/scss/sections/_member_edit.scss @@ -33,5 +33,9 @@ .member-card__details { text-align: right; + + .icon-link { + margin: 0 -$gap; + } } } \ No newline at end of file diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 140e8a26..24893bf2 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -19,7 +19,7 @@

    {{ member_name }}

    -
    Workspace Role
    {{member_workspace_role}}
    +
    Workspace Role
    {{member_workspace_role}}
    @@ -57,7 +57,7 @@ Development
    - no access set role + no access set role
  • @@ -65,7 +65,7 @@ Sandbox
    - no accessset role + no accessset role
  • @@ -73,7 +73,7 @@ Production
    - Billingset role + Billingset role
  • @@ -82,7 +82,7 @@

    {% module Icon('arrow-right') %} Digital Dojo

    - no access + no access
    From 10cdfcbbaba4e9390acbf861658c83fa32502b11 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 14:44:59 -0400 Subject: [PATCH 019/173] Add models dir --- atst/models/__init__.py | 0 atst/models/request.py | 32 ++++++++++++++++++++++++++++++++ atst/models/status_event.py | 17 +++++++++++++++++ atst/models/types.py | 10 ++++++++++ 4 files changed, 59 insertions(+) create mode 100644 atst/models/__init__.py create mode 100644 atst/models/request.py create mode 100644 atst/models/status_event.py create mode 100644 atst/models/types.py diff --git a/atst/models/__init__.py b/atst/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/atst/models/request.py b/atst/models/request.py new file mode 100644 index 00000000..5762e857 --- /dev/null +++ b/atst/models/request.py @@ -0,0 +1,32 @@ +from sqlalchemy import Column, func +from sqlalchemy.types import DateTime +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import relationship + +from requests_queue.models import Base +from requests_queue.models.types import Id + + +class Request(Base): + __tablename__ = 'requests' + + id = Id() + creator = Column(UUID(as_uuid=True)) + time_created = Column(DateTime(timezone=True), server_default=func.now()) + body = Column(JSONB) + status_events = relationship('StatusEvent', + backref='request', + order_by='StatusEvent.sequence') + + @property + def status(self): + return self.status_events[-1].new_status + + @property + def action_required_by(self): + return { + "incomplete": "mission_owner", + "pending_submission": "mission_owner", + "submitted": "ccpo", + "approved": "mission_owner", + }.get(self.status) diff --git a/atst/models/status_event.py b/atst/models/status_event.py new file mode 100644 index 00000000..c5c5c715 --- /dev/null +++ b/atst/models/status_event.py @@ -0,0 +1,17 @@ +from sqlalchemy import Column, func, ForeignKey +from sqlalchemy.types import DateTime, String, BigInteger +from sqlalchemy.schema import Sequence +from sqlalchemy.dialects.postgresql import UUID + +from requests_queue.models import Base +from requests_queue.models.types import Id + + +class StatusEvent(Base): + __tablename__ = 'status_events' + + id = Id() + new_status = Column(String()) + time_created = Column(DateTime(timezone=True), server_default=func.now()) + request_id = Column(UUID(as_uuid=True), ForeignKey('requests.id', ondelete='CASCADE')) + sequence = Column(BigInteger, Sequence('status_events_sequence_seq'), nullable=False) diff --git a/atst/models/types.py b/atst/models/types.py new file mode 100644 index 00000000..b2e1c6d7 --- /dev/null +++ b/atst/models/types.py @@ -0,0 +1,10 @@ +import sqlalchemy +from sqlalchemy import Column +from sqlalchemy.dialects.postgresql import UUID + + +def Id(): + return Column( + UUID(as_uuid=True), + primary_key=True, + server_default=sqlalchemy.text("uuid_generate_v4()")) From 8a80ba426f2eee47c3b884abb27bbf7a3d325a5c Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 14:45:08 -0400 Subject: [PATCH 020/173] Merge pipfiles --- Pipfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Pipfile b/Pipfile index eb946fb9..81cadd0d 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,9 @@ Unipath = "==1.1" wtforms-tornado = "*" pendulum = "*" redis = "*" +sqlalchemy = "*" +alembic = "*" +"psycopg2-binary" = "*" [dev-packages] bandit = "*" @@ -20,6 +23,7 @@ ipdb = "*" pylint = "*" black = "*" pytest-watch = "*" +factory-boy = "*" [requires] python_version = "3.6" From c6636bec780ef5028f33f73920f334eedc18b34e Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 14:58:26 -0400 Subject: [PATCH 021/173] Models and migrations for requests --- Pipfile.lock | 180 ++++++++++++------ alembic.ini | 74 +++++++ alembic/README | 1 + alembic/env.py | 85 +++++++++ alembic/script.py.mako | 24 +++ alembic/versions/b5b17d465166_requests.py | 44 +++++ .../ff1c9c02fa61_enable_uuid_extension.py | 26 +++ atst/database.py | 8 + atst/models/__init__.py | 6 + atst/models/request.py | 4 +- ...tatus_event.py => request_status_event.py} | 10 +- config/base.ini | 1 + 12 files changed, 401 insertions(+), 62 deletions(-) create mode 100644 alembic.ini create mode 100644 alembic/README create mode 100644 alembic/env.py create mode 100644 alembic/script.py.mako create mode 100644 alembic/versions/b5b17d465166_requests.py create mode 100644 alembic/versions/ff1c9c02fa61_enable_uuid_extension.py create mode 100644 atst/database.py rename atst/models/{status_event.py => request_status_event.py} (63%) diff --git a/Pipfile.lock b/Pipfile.lock index 2fadae1e..d87dfa97 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "3bea02ccdb0e3877f2595d7fb405408114ec8947e0484d5b4aaf14a4c8ff78b2" + "sha256": "7cd87f2c2c42bc776a6aa6f72fcbb8b30d4e703e50b6480ce1c8ace6ae6dd0a4" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,26 @@ ] }, "default": { + "alembic": { + "hashes": [ + "sha256:52d73b1d750f1414fa90c25a08da47b87de1e4ad883935718a8f36396e19e78e", + "sha256:eb7db9b4510562ec37c91d00b00d95fde076c1030d3f661aea882eec532b3565" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "mako": { + "hashes": [ + "sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae" + ], + "version": "==1.0.7" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, "pendulum": { "hashes": [ "sha256:0643d45824e6789b88187728337dfa6075a0233f6976c2abefba00d064156309", @@ -32,6 +52,42 @@ "index": "pypi", "version": "==2.0.2" }, + "psycopg2-binary": { + "hashes": [ + "sha256:04afb59bbbd2eab3148e6816beddc74348078b8c02a1113ea7f7822f5be4afe3", + "sha256:098b18f4d8857a8f9b206d1dc54db56c2255d5d26458917e7bcad61ebfe4338f", + "sha256:0bf855d4a7083e20ead961fda4923887094eaeace0ab2d76eb4aa300f4bbf5bd", + "sha256:197dda3ffd02057820be83fe4d84529ea70bf39a9a4daee1d20ffc74eb3d042e", + "sha256:278ef63afb4b3d842b4609f2c05ffbfb76795cf6a184deeb8707cd5ed3c981a5", + "sha256:3cbf8c4fc8f22f0817220891cf405831559f4d4c12c4f73913730a2ea6c47a47", + "sha256:4305aed922c4d9d6163ab3a41d80b5a1cfab54917467da8168552c42cad84d32", + "sha256:47ee296f704fb8b2a616dec691cdcfd5fa0f11943955e88faa98cbd1dc3b3e3d", + "sha256:4a0e38cb30457e70580903367161173d4a7d1381eb2f2cfe4e69b7806623f484", + "sha256:4d6c294c6638a71cafb82a37f182f24321f1163b08b5d5ca076e11fe838a3086", + "sha256:4f3233c366500730f839f92833194fd8f9a5c4529c8cd8040aa162c3740de8e5", + "sha256:5221f5a3f4ca2ddf0d58e8b8a32ca50948be9a43351fda797eb4e72d7a7aa34d", + "sha256:5c6ca0b507540a11eaf9e77dee4f07c131c2ec80ca0cffa146671bf690bc1c02", + "sha256:789bd89d71d704db2b3d5e67d6d518b158985d791d3b2dec5ab85457cfc9677b", + "sha256:7b94d29239efeaa6a967f3b5971bd0518d2a24edd1511edbf4a2c8b815220d07", + "sha256:89bc65ef3301c74cf32db25334421ea6adbe8f65601ea45dcaaf095abed910bb", + "sha256:89d6d3a549f405c20c9ae4dc94d7ed2de2fa77427a470674490a622070732e62", + "sha256:97521704ac7127d7d8ba22877da3c7bf4a40366587d238ec679ff38e33177498", + "sha256:a395b62d5f44ff6f633231abe568e2203b8fabf9797cd6386aa92497df912d9a", + "sha256:a6d32c37f714c3f34158f3fa659f3a8f2658d5f53c4297d45579b9677cc4d852", + "sha256:a89ee5c26f72f2d0d74b991ce49e42ddeb4ac0dc2d8c06a0f2770a1ab48f4fe0", + "sha256:b4c8b0ef3608e59317bfc501df84a61e48b5445d45f24d0391a24802de5f2d84", + "sha256:b5fcf07140219a1f71e18486b8dc28e2e1b76a441c19374805c617aa6d9a9d55", + "sha256:b86f527f00956ecebad6ab3bb30e3a75fedf1160a8716978dd8ce7adddedd86f", + "sha256:be4c4aa22ba22f70de36c98b06480e2f1697972d49eb20d525f400d204a6d272", + "sha256:c2ac7aa1a144d4e0e613ac7286dae85671e99fe7a1353954d4905629c36b811c", + "sha256:de26ef4787b5e778e8223913a3e50368b44e7480f83c76df1f51d23bd21cea16", + "sha256:e70ebcfc5372dc7b699c0110454fc4263967f30c55454397e5769eb72c0eb0ce", + "sha256:eadbd32b6bc48b67b0457fccc94c86f7ccc8178ab839f684eb285bb592dc143e", + "sha256:ecbc6dfff6db06b8b72ae8a2f25ff20fbdcb83cb543811a08f7cb555042aa729" + ], + "index": "pypi", + "version": "==2.7.5" + }, "python-dateutil": { "hashes": [ "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", @@ -39,12 +95,18 @@ ], "version": "==2.7.3" }, + "python-editor": { + "hashes": [ + "sha256:a3c066acee22a1c94f63938341d4fb374e3fdd69366ed6603d7b24bed1efc565" + ], + "version": "==1.0.3" + }, "pytzdata": { "hashes": [ "sha256:1d936da41ee06216d89fdc7ead1ee9a5da2811a8787515a976b646e110c3f622", "sha256:e4ef42e82b0b493c5849eed98b5ab49d6767caf982127e9a33167f1153b36cc5" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", + "markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.3.*' and python_version >= '2.7'", "version": "==2018.5" }, "redis": { @@ -62,6 +124,13 @@ ], "version": "==1.11.0" }, + "sqlalchemy": { + "hashes": [ + "sha256:72325e67fb85f6e9ad304c603d83626d1df684fdf0c7ab1f0352e71feeab69d8" + ], + "index": "pypi", + "version": "==1.2.10" + }, "tornado": { "hashes": [ "sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7", @@ -128,10 +197,10 @@ }, "astroid": { "hashes": [ - "sha256:a8d8c7fe34e34e868426b9bafce852c355a3951eef60bc831b2ed541558f8d37", - "sha256:e722228b5259ce8c7cbf75f3b0ee8b483cfbd4df01167474a84087d1aeade22c" + "sha256:0a0c484279a5f08c9bcedd6fa9b42e378866a7dcc695206b92d59dc9f2d9760d", + "sha256:218e36cf8d98a42f16214e8670819ce307fa707d1dcf7f9af84c7aede1febc7f" ], - "version": "==2.0.0.dev4" + "version": "==2.0.1" }, "atomicwrites": { "hashes": [ @@ -197,19 +266,35 @@ ], "version": "==0.6.2" }, + "factory-boy": { + "hashes": [ + "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", + "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" + ], + "index": "pypi", + "version": "==2.11.1" + }, + "faker": { + "hashes": [ + "sha256:0e9a1227a3a0f3297a485715e72ee6eb77081b17b629367042b586e38c03c867", + "sha256:b4840807a94a3bad0217d6ed3f9b65a1cc6e1db1c99e1184673056ae2c0a4c4d" + ], + "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*'", + "version": "==0.8.17" + }, "gitdb2": { "hashes": [ - "sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09", - "sha256:cf9a4b68e8c4da8d42e48728c944ff7af2d8c9db303ac1ab32eac37aa4194b0e" + "sha256:87783b7f4a8f6b71c7fe81d32179b3c8781c1a7d6fa0c69bff2f315b00aff4f8", + "sha256:bb4c85b8a58531c51373c89f92163b92f30f81369605a67cd52d1fc21246c044" ], - "version": "==2.0.3" + "version": "==2.0.4" }, "gitpython": { "hashes": [ - "sha256:1ec4c44846cf76a1e55769560673a97731849c9d05401e035e607495f10db959", - "sha256:b60b045cf64a321e5b620debb49890099fa6c7be6dfb7fb249027e5d34227301" + "sha256:563221e5a44369c6b79172f455584c9ebbb122a13368cc82cb4b5addff788f82", + "sha256:8237dc5bfd6f1366abeee5624111b9d6879393d84745a507de0fda86043b65a8" ], - "version": "==2.1.10" + "version": "==2.1.11" }, "ipdb": { "hashes": [ @@ -239,7 +324,7 @@ "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", + "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", "version": "==4.3.4" }, "jedi": { @@ -313,10 +398,10 @@ }, "pbr": { "hashes": [ - "sha256:4f2b11d95917af76e936811be8361b2b19616e5ef3b55956a429ec7864378e0c", - "sha256:e0f23b61ec42473723b2fec2f33fb12558ff221ee551962f01dd4de9053c2055" + "sha256:754e766b4f4bad3aa68cfd532456298da1aa39375da8748392dbae90860d5f18", + "sha256:c6bddbad814f23c7faaf88d8a186e9965243cc6206a23361b73023648e645794" ], - "version": "==4.1.0" + "version": "==4.1.1" }, "pexpect": { "hashes": [ @@ -339,7 +424,7 @@ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", + "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", "version": "==0.6.0" }, "prompt-toolkit": { @@ -362,7 +447,7 @@ "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", + "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", "version": "==1.5.4" }, "pygments": { @@ -374,11 +459,11 @@ }, "pylint": { "hashes": [ - "sha256:285c9ae7255acb584057fe31051a37498985e632b99fc0ec93b7eb38a1b137f9", - "sha256:dd5c0fc4e6a4cb9483a4367699099a7dfc8a13de9ecac4cb16855ffac68d49de" + "sha256:2c90a24bee8fae22ac98061c896e61f45c5b73c2e0511a4bf53f99ba56e90434", + "sha256:454532779425098969b8f54ab0f056000b883909f69d05905ea114df886e3251" ], "index": "pypi", - "version": "==2.0.0.dev2" + "version": "==2.0.1" }, "pytest": { "hashes": [ @@ -403,6 +488,13 @@ "index": "pypi", "version": "==4.2.0" }, + "python-dateutil": { + "hashes": [ + "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", + "sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8" + ], + "version": "==2.7.3" + }, "pyyaml": { "hashes": [ "sha256:254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb", @@ -428,17 +520,24 @@ }, "smmap2": { "hashes": [ - "sha256:b78ee0f1f5772d69ff50b1cbdb01b8c6647a8354f02f23b488cf4b2cfc923956", - "sha256:c7530db63f15f09f8251094b22091298e82bf6c699a6b8344aaaef3f2e1276c3" + "sha256:0dd53d991af487f9b22774fa89451358da3607c02b9b886a54736c6a313ece0b", + "sha256:dc216005e529d57007ace27048eb336dcecb7fc413cfb3b2f402bb25972b69c6" ], - "version": "==2.0.3" + "version": "==2.0.4" }, "stevedore": { "hashes": [ - "sha256:e3d96b2c4e882ec0c1ff95eaebf7b575a779fd0ccb4c741b9832bed410d58b3d", - "sha256:f1c7518e7b160336040fee272174f1f7b29a46febb3632502a8f2055f973d60b" + "sha256:1e153545aca7a6a49d8337acca4f41c212fbfa60bf864ecd056df0cafb9627e8", + "sha256:c7eac1c0d95824c88b655273da5c17cdde6482b2739f47c30bf851dcc9d3c2c0" ], - "version": "==1.28.0" + "version": "==1.29.0" + }, + "text-unidecode": { + "hashes": [ + "sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d", + "sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc" + ], + "version": "==1.2" }, "toml": { "hashes": [ @@ -464,35 +563,6 @@ ], "version": "==4.3.2" }, - "typed-ast": { - "hashes": [ - "sha256:0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", - "sha256:10703d3cec8dcd9eef5a630a04056bbc898abc19bac5691612acba7d1325b66d", - "sha256:1f6c4bd0bdc0f14246fd41262df7dfc018d65bb05f6e16390b7ea26ca454a291", - "sha256:25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", - "sha256:29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", - "sha256:2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", - "sha256:3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", - "sha256:519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", - "sha256:57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa", - "sha256:668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", - "sha256:68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", - "sha256:6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", - "sha256:79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", - "sha256:8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", - "sha256:898f818399cafcdb93cbbe15fc83a33d05f18e29fb498ddc09b0214cdfc7cd51", - "sha256:94b091dc0f19291adcb279a108f5d38de2430411068b219f41b343c03b28fb1f", - "sha256:a26863198902cda15ab4503991e8cf1ca874219e0118cbf07c126bce7c4db129", - "sha256:a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", - "sha256:bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", - "sha256:c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", - "sha256:c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", - "sha256:edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", - "sha256:f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6" - ], - "markers": "python_version < '3.7' and implementation_name == 'cpython'", - "version": "==1.1.0" - }, "watchdog": { "hashes": [ "sha256:7e65882adb7746039b6f3876ee174952f8eaaa34491ba34333ddf1fe35de4162" diff --git a/alembic.ini b/alembic.ini new file mode 100644 index 00000000..08ce3124 --- /dev/null +++ b/alembic.ini @@ -0,0 +1,74 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +script_location = alembic + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# timezone to use when rendering the date +# within the migration file as well as the filename. +# string value is passed to dateutil.tz.gettz() +# leave blank for localtime +# timezone = + +# max length of characters to apply to the +# "slug" field +#truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# version location specification; this defaults +# to alembic/versions. When using multiple version +# directories, initial revisions must be specified with --version-path +# version_locations = %(here)s/bar %(here)s/bat alembic/versions + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = driver://user:pass@localhost/dbname + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/alembic/README b/alembic/README new file mode 100644 index 00000000..98e4f9c4 --- /dev/null +++ b/alembic/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/alembic/env.py b/alembic/env.py new file mode 100644 index 00000000..6a9d9749 --- /dev/null +++ b/alembic/env.py @@ -0,0 +1,85 @@ +from __future__ import with_statement +from alembic import context +from sqlalchemy import engine_from_config, pool +from logging.config import fileConfig + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +target_metadata = None + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + +import sys +from unipath import Path + +parent_dir = Path(__file__).parent.parent +sys.path.append(parent_dir) + +from atst.app import make_config +app_config = make_config() +config.set_main_option('sqlalchemy.url', app_config['default']['DATABASE_URI']) + +from atst.database import make_db +from atst.models import * +db = make_db(app_config) +target_metadata = Base.metadata + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata + ) + + with context.begin_transaction(): + context.run_migrations() + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/alembic/script.py.mako b/alembic/script.py.mako new file mode 100644 index 00000000..2c015630 --- /dev/null +++ b/alembic/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/alembic/versions/b5b17d465166_requests.py b/alembic/versions/b5b17d465166_requests.py new file mode 100644 index 00000000..dd701f9c --- /dev/null +++ b/alembic/versions/b5b17d465166_requests.py @@ -0,0 +1,44 @@ +"""requests + +Revision ID: b5b17d465166 +Revises: ff1c9c02fa61 +Create Date: 2018-07-23 14:58:05.044456 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'b5b17d465166' +down_revision = 'ff1c9c02fa61' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('requests', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('creator', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('time_created', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('body', postgresql.JSONB(astext_type=sa.Text()), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('request_status_events', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('new_status', sa.String(), nullable=True), + sa.Column('time_created', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('request_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('sequence', sa.BigInteger(), nullable=False), + sa.ForeignKeyConstraint(['request_id'], ['requests.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('request_status_events') + op.drop_table('requests') + # ### end Alembic commands ### diff --git a/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py b/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py new file mode 100644 index 00000000..a6f6206a --- /dev/null +++ b/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py @@ -0,0 +1,26 @@ +"""enable uuid extension + +Revision ID: ff1c9c02fa61 +Revises: +Create Date: 2018-07-23 14:54:05.422286 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ff1c9c02fa61' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + connection = op.get_bind() + connection.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"') + + +def downgrade(): + connection = op.get_bind() + connection.execute('DROP EXTENSION IF EXISTS "uuid-ossp"') diff --git a/atst/database.py b/atst/database.py new file mode 100644 index 00000000..6191f62e --- /dev/null +++ b/atst/database.py @@ -0,0 +1,8 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, scoped_session + + +def make_db(config): + engine = create_engine(config['default']['DATABASE_URI']) + session = scoped_session(sessionmaker(bind=engine)) + return session diff --git a/atst/models/__init__.py b/atst/models/__init__.py index e69de29b..ef5d9457 100644 --- a/atst/models/__init__.py +++ b/atst/models/__init__.py @@ -0,0 +1,6 @@ +from sqlalchemy.ext.declarative import declarative_base + +Base = declarative_base() + +from .request import Request +from .request_status_event import RequestStatusEvent diff --git a/atst/models/request.py b/atst/models/request.py index 5762e857..baaa92b3 100644 --- a/atst/models/request.py +++ b/atst/models/request.py @@ -3,8 +3,8 @@ from sqlalchemy.types import DateTime from sqlalchemy.dialects.postgresql import JSONB, UUID from sqlalchemy.orm import relationship -from requests_queue.models import Base -from requests_queue.models.types import Id +from atst.models import Base +from atst.models.types import Id class Request(Base): diff --git a/atst/models/status_event.py b/atst/models/request_status_event.py similarity index 63% rename from atst/models/status_event.py rename to atst/models/request_status_event.py index c5c5c715..d7c363cd 100644 --- a/atst/models/status_event.py +++ b/atst/models/request_status_event.py @@ -3,15 +3,15 @@ from sqlalchemy.types import DateTime, String, BigInteger from sqlalchemy.schema import Sequence from sqlalchemy.dialects.postgresql import UUID -from requests_queue.models import Base -from requests_queue.models.types import Id +from atst.models import Base +from atst.models.types import Id -class StatusEvent(Base): - __tablename__ = 'status_events' +class RequestStatusEvent(Base): + __tablename__ = 'request_status_events' id = Id() new_status = Column(String()) time_created = Column(DateTime(timezone=True), server_default=func.now()) request_id = Column(UUID(as_uuid=True), ForeignKey('requests.id', ondelete='CASCADE')) - sequence = Column(BigInteger, Sequence('status_events_sequence_seq'), nullable=False) + sequence = Column(BigInteger, Sequence('request_status_events_sequence_seq'), nullable=False) diff --git a/config/base.ini b/config/base.ini index 431eacf7..8b6e68a2 100644 --- a/config/base.ini +++ b/config/base.ini @@ -11,3 +11,4 @@ CAC_URL = https://localhost:8001 REQUESTS_QUEUE_BASE_URL = http://localhost:8003 REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 +DATABASE_URI = postgres://postgres:postgres@localhost/atat From 5f7720deeede3a1213b69b98fc46a36d9a10de93 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 15:23:09 -0400 Subject: [PATCH 022/173] Requests page working --- alembic/versions/b5b17d465166_requests.py | 3 + atst/app.py | 4 +- atst/domain/__init__.py | 0 atst/domain/exceptions.py | 16 +++ atst/domain/requests.py | 130 ++++++++++++++++++++++ atst/handlers/request.py | 20 ++-- atst/models/request.py | 4 +- 7 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 atst/domain/__init__.py create mode 100644 atst/domain/exceptions.py create mode 100644 atst/domain/requests.py diff --git a/alembic/versions/b5b17d465166_requests.py b/alembic/versions/b5b17d465166_requests.py index dd701f9c..b8d47c06 100644 --- a/alembic/versions/b5b17d465166_requests.py +++ b/alembic/versions/b5b17d465166_requests.py @@ -36,6 +36,9 @@ def upgrade(): ) # ### end Alembic commands ### + db = op.get_bind() + db.execute("CREATE SEQUENCE request_status_events_sequence_seq OWNED BY request_status_events.sequence;") + def downgrade(): # ### commands auto generated by Alembic - please adjust! ### diff --git a/atst/app.py b/atst/app.py index aa101838..058a3046 100644 --- a/atst/app.py +++ b/atst/app.py @@ -20,6 +20,7 @@ from atst.api_client import ApiClient from atst.sessions import RedisSessions from atst import ui_modules from atst import ui_methods +from atst.database import make_db ENV = os.getenv("TORNADO_ENV", "dev") @@ -55,7 +56,7 @@ def make_app(config, deps, **kwargs): url( r"/requests", Request, - {"page": "requests", "requests_client": deps["requests_client"]}, + {"page": "requests", "db_session": deps["db_session"]}, name="requests", ), url( @@ -160,6 +161,7 @@ def make_deps(config): ) return { + "db_session": make_db(config), "authz_client": ApiClient( config["default"]["AUTHZ_BASE_URL"], api_version="v1", diff --git a/atst/domain/__init__.py b/atst/domain/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/atst/domain/exceptions.py b/atst/domain/exceptions.py new file mode 100644 index 00000000..802997d4 --- /dev/null +++ b/atst/domain/exceptions.py @@ -0,0 +1,16 @@ +class NotFoundError(Exception): + def __init__(self, resource_name): + self.resource_name = resource_name + + @property + def message(self): + return "No {} could be found.".format(self.resource_name) + + +class AlreadyExistsError(Exception): + def __init__(self, resource_name): + self.resource_name = resource_name + + @property + def message(self): + return "{} already exists".format(self.resource_name) diff --git a/atst/domain/requests.py b/atst/domain/requests.py new file mode 100644 index 00000000..09acb0af --- /dev/null +++ b/atst/domain/requests.py @@ -0,0 +1,130 @@ +import tornado.gen +from sqlalchemy import exists, and_ +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.orm.attributes import flag_modified + +from atst.models import Request, RequestStatusEvent +from .exceptions import NotFoundError + + +def deep_merge(source, destination: dict): + """ + Merge source dict into destination dict recursively. + """ + + def _deep_merge(a, b): + for key, value in a.items(): + if isinstance(value, dict): + node = b.setdefault(key, {}) + _deep_merge(value, node) + else: + b[key] = value + + return b + + return _deep_merge(source, dict(destination)) + + +class Requests(object): + AUTO_APPROVE_THRESHOLD = 1000000 + + def __init__(self, db_session): + self.db_session = db_session + + def create(self, creator_id, body): + request = Request(creator=creator_id, body=body) + + status_event = RequestStatusEvent(new_status="incomplete") + request.status_events.append(status_event) + + self.db_session.add(request) + self.db_session.commit() + + return request + + def exists(self, request_id, creator_id): + return self.db_session.query( + exists().where( + and_(Request.id == request_id, Request.creator == creator_id) + ) + ).scalar() + + def get(self, request_id): + try: + request = self.db_session.query(Request).filter_by(id=request_id).one() + except NoResultFound: + raise NotFoundError("request") + + return request + + def get_many(self, creator_id=None): + filters = [] + if creator_id: + filters.append(Request.creator == creator_id) + + requests = ( + self.db_session.query(Request) + .filter(*filters) + .order_by(Request.time_created.desc()) + .all() + ) + return requests + + @tornado.gen.coroutine + def submit(self, request): + request.status_events.append(StatusEvent(new_status="submitted")) + + if Requests.should_auto_approve(request): + request.status_events.append(StatusEvent(new_status="approved")) + + self.db_session.add(request) + self.db_session.commit() + + return request + + @tornado.gen.coroutine + def update(self, request_id, request_delta): + try: + # Query for request matching id, acquiring a row-level write lock. + # https://www.postgresql.org/docs/10/static/sql-select.html#SQL-FOR-UPDATE-SHARE + request = ( + self.db_session.query(Request) + .filter_by(id=request_id) + .with_for_update(of=Request) + .one() + ) + except NoResultFound: + return + + request.body = deep_merge(request_delta, request.body) + + if Requests.should_allow_submission(request): + request.status_events.append(StatusEvent(new_status="pending_submission")) + + # Without this, sqlalchemy won't notice the change to request.body, + # since it doesn't track dictionary mutations by default. + flag_modified(request, "body") + + self.db_session.add(request) + self.db_session.commit() + + @classmethod + def should_auto_approve(cls, request): + try: + dollar_value = request.body["details_of_use"]["dollar_value"] + except KeyError: + return False + + return dollar_value < cls.AUTO_APPROVE_THRESHOLD + + @classmethod + def should_allow_submission(cls, request): + all_request_sections = [ + "details_of_use", + "information_about_you", + "primary_poc", + ] + existing_request_sections = request.body.keys() + return request.status == "incomplete" and all( + section in existing_request_sections for section in all_request_sections + ) diff --git a/atst/handlers/request.py b/atst/handlers/request.py index d9bec160..1373280a 100644 --- a/atst/handlers/request.py +++ b/atst/handlers/request.py @@ -2,16 +2,17 @@ import tornado import pendulum from atst.handler import BaseHandler +from atst.domain.requests import Requests def map_request(user, request): - time_created = pendulum.parse(request["time_created"]) + time_created = pendulum.instance(request.time_created) is_new = time_created.add(days=1) > pendulum.now() return { - "order_id": request["id"], + "order_id": request.id, "is_new": is_new, - "status": request["status"], + "status": request.status, "app_count": 1, "date": time_created.format("M/DD/YYYY"), "full_name": "{} {}".format(user["first_name"], user["last_name"]), @@ -19,9 +20,9 @@ def map_request(user, request): class Request(BaseHandler): - def initialize(self, page, requests_client): + def initialize(self, page, db_session): self.page = page - self.requests_client = requests_client + self.requests = Requests(db_session) @tornado.web.authenticated @tornado.gen.coroutine @@ -33,11 +34,10 @@ class Request(BaseHandler): @tornado.gen.coroutine def fetch_requests(self, user): + requests = [] if "review_and_approve_jedi_workspace_request" in user["atat_permissions"]: - response = yield self.requests_client.get("/requests") + requests = self.requests.get_many() else: - response = yield self.requests_client.get( - "/requests?creator_id={}".format(user["id"]) - ) + requests = self.requests.get_many(creator_id=user["id"]) - return response.json["requests"] + return requests diff --git a/atst/models/request.py b/atst/models/request.py index baaa92b3..42bec6ed 100644 --- a/atst/models/request.py +++ b/atst/models/request.py @@ -14,9 +14,9 @@ class Request(Base): creator = Column(UUID(as_uuid=True)) time_created = Column(DateTime(timezone=True), server_default=func.now()) body = Column(JSONB) - status_events = relationship('StatusEvent', + status_events = relationship('RequestStatusEvent', backref='request', - order_by='StatusEvent.sequence') + order_by='RequestStatusEvent.sequence') @property def status(self): From 6444453ca0e99058f89197c36dd00b6b1f7b7fdd Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 15:58:57 -0400 Subject: [PATCH 023/173] Fix request_new --- atst/app.py | 6 +-- atst/domain/requests.py | 6 +-- atst/handlers/request_new.py | 83 ++++++++++++++++-------------------- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/atst/app.py b/atst/app.py index 058a3046..64e87e56 100644 --- a/atst/app.py +++ b/atst/app.py @@ -64,7 +64,7 @@ def make_app(config, deps, **kwargs): RequestNew, { "page": "requests_new", - "requests_client": deps["requests_client"], + "db_session": deps["db_session"], "fundz_client": deps["fundz_client"], }, name="request_new", @@ -74,7 +74,7 @@ def make_app(config, deps, **kwargs): RequestNew, { "page": "requests_new", - "requests_client": deps["requests_client"], + "db_session": deps["db_session"], "fundz_client": deps["fundz_client"], }, name="request_form_new", @@ -84,7 +84,7 @@ def make_app(config, deps, **kwargs): RequestNew, { "page": "requests_new", - "requests_client": deps["requests_client"], + "db_session": deps["db_session"], "fundz_client": deps["fundz_client"], }, name="request_form_update", diff --git a/atst/domain/requests.py b/atst/domain/requests.py index 09acb0af..aa37b932 100644 --- a/atst/domain/requests.py +++ b/atst/domain/requests.py @@ -72,10 +72,10 @@ class Requests(object): @tornado.gen.coroutine def submit(self, request): - request.status_events.append(StatusEvent(new_status="submitted")) + request.status_events.append(RequestStatusEvent(new_status="submitted")) if Requests.should_auto_approve(request): - request.status_events.append(StatusEvent(new_status="approved")) + request.status_events.append(RequestStatusEvent(new_status="approved")) self.db_session.add(request) self.db_session.commit() @@ -99,7 +99,7 @@ class Requests(object): request.body = deep_merge(request_delta, request.body) if Requests.should_allow_submission(request): - request.status_events.append(StatusEvent(new_status="pending_submission")) + request.status_events.append(RequestStatusEvent(new_status="pending_submission")) # Without this, sqlalchemy won't notice the change to request.body, # since it doesn't track dictionary mutations by default. diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index d71c307e..49454874 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -9,17 +9,16 @@ from atst.forms.review import ReviewForm class RequestNew(BaseHandler): - def initialize(self, page, requests_client, fundz_client): + def initialize(self, page, db_session, fundz_client): self.page = page - self.requests_client = requests_client + self.requests_repo = Requests(db_session) self.fundz_client = fundz_client - @tornado.gen.coroutine def get_existing_request(self, request_id): if request_id is None: - return {} - request = yield self.requests_client.get("/requests/{}".format(request_id)) - return request.json + return None + request = self.requests_repo.get(request_id) + return request @tornado.web.authenticated @tornado.gen.coroutine @@ -28,9 +27,9 @@ class RequestNew(BaseHandler): screen = int(screen) post_data = self.request.arguments current_user = self.get_current_user() - existing_request = yield self.get_existing_request(request_id) + existing_request = self.get_existing_request(request_id) jedi_flow = JEDIRequestFlow( - self.requests_client, + self.requests_repo, self.fundz_client, screen, post_data=post_data, @@ -50,24 +49,21 @@ class RequestNew(BaseHandler): ) if jedi_flow.validate(): - response = yield jedi_flow.create_or_update_request() - if response.ok: - valid = yield jedi_flow.validate_warnings() - if valid: - if jedi_flow.next_screen > len(jedi_flow.screens): - where = "/requests" - else: - where = self.application.default_router.reverse_url( - "request_form_update", jedi_flow.next_screen, jedi_flow.request_id - ) - self.redirect(where) + request = jedi_flow.create_or_update_request() + valid = yield jedi_flow.validate_warnings() + if valid: + if jedi_flow.next_screen > len(jedi_flow.screens): + where = "/requests" else: - self.render( - "requests/screen-%d.html.to" % int(screen), - **rerender_args + where = self.application.default_router.reverse_url( + "request_form_update", jedi_flow.next_screen, jedi_flow.request_id ) + self.redirect(where) else: - self.set_status(response.code) + self.render( + "requests/screen-%d.html.to" % int(screen), + **rerender_args + ) else: self.render( "requests/screen-%d.html.to" % int(screen), @@ -81,15 +77,10 @@ class RequestNew(BaseHandler): request = None if request_id: - response = yield self.requests_client.get( - "/requests/{}".format(request_id), - raise_error=False, - ) - if response.ok: - request = response.json + request = self.requests_repo.get(request_id) jedi_flow = JEDIRequestFlow( - self.requests_client, self.fundz_client, screen, request, request_id=request_id + self.requests_repo, self.fundz_client, screen, request, request_id=request_id ) self.render( @@ -108,7 +99,7 @@ class RequestNew(BaseHandler): class JEDIRequestFlow(object): def __init__( self, - requests_client, + requests_repo, fundz_client, current_step, request=None, @@ -117,7 +108,7 @@ class JEDIRequestFlow(object): current_user=None, existing_request=None, ): - self.requests_client = requests_client + self.requests_repo = requests_repo self.fundz_client = fundz_client self.current_step = current_step @@ -145,8 +136,13 @@ class JEDIRequestFlow(object): @tornado.gen.coroutine def validate_warnings(self): + existing_request_data = ( + self.existing_request + and self.existing_request.body.get(self.form_section) + ) or None + valid = yield self.form.perform_extra_validation( - self.existing_request.get('body', {}).get(self.form_section), + existing_request_data, self.fundz_client, ) return valid @@ -171,15 +167,15 @@ class JEDIRequestFlow(object): if self.request: if self.form_section == "review_submit": - data = self.request["body"] + data = self.request.body else: - data = self.request["body"].get(self.form_section, {}) + data = self.request.body.get(self.form_section, {}) return defaultdict(lambda: defaultdict(lambda: 'Input required'), data) @property def can_submit(self): - return self.request and self.request["status"] != "incomplete" + return self.request and self.request.status != "incomplete" @property def next_screen(self): @@ -222,19 +218,12 @@ class JEDIRequestFlow(object): }, ] - @tornado.gen.coroutine def create_or_update_request(self): request_data = { - "creator_id": self.current_user["id"], - "request": {self.form_section: self.form.data}, + self.form_section: self.form.data } if self.request_id: - response = yield self.requests_client.patch( - "/requests/{}".format(self.request_id), json=request_data - ) + self.requests_repo.update(self.request_id, request_data) else: - response = yield self.requests_client.post("/requests", json=request_data) - self.request = response.json - self.request_id = self.request["id"] - - return response + request = self.requests_repo.create(self.current_user["id"], request_data) + self.request_id = request.id From 0400e2c864fafa9a9607524f0ac60c87354e762e Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 16:04:06 -0400 Subject: [PATCH 024/173] Update requests_submit --- atst/app.py | 2 +- atst/handlers/request_submit.py | 22 ++++++---------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/atst/app.py b/atst/app.py index 64e87e56..922b2ca7 100644 --- a/atst/app.py +++ b/atst/app.py @@ -92,7 +92,7 @@ def make_app(config, deps, **kwargs): url( r"/requests/submit/(\S+)", RequestsSubmit, - {"requests_client": deps["requests_client"]}, + {"db_session": deps["db_session"]}, name="requests_submit", ), # Dummy request/approval screen diff --git a/atst/handlers/request_submit.py b/atst/handlers/request_submit.py index f4d19b3d..ff27803b 100644 --- a/atst/handlers/request_submit.py +++ b/atst/handlers/request_submit.py @@ -1,29 +1,19 @@ import tornado from atst.handler import BaseHandler +from atst.domain.requests import Requests class RequestsSubmit(BaseHandler): - def initialize(self, requests_client): - self.requests_client = requests_client + def initialize(self, db_session): + self.requests_repo = Requests(db_session) @tornado.web.authenticated @tornado.gen.coroutine def post(self, request_id): - yield self.requests_client.post( - "/requests/{}/submit".format(request_id), - allow_nonstandard_methods=True - ) - approved = yield self._check_approved(request_id) - if approved: + request = self.requests_repo.get(request_id) + request = yield self.requests_repo.submit(request) + if request.status == "approved": self.redirect("/requests?modal=True") else: self.redirect("/requests") - - @tornado.gen.coroutine - def _check_approved(self, request_id): - response = yield self.requests_client.get( - "/requests/{}".format(request_id) - ) - status = response.json.get("status") - return status == "approved" From fadbf1cfb14fcab495ab625e6236ee50f55a36a2 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 16:19:12 -0400 Subject: [PATCH 025/173] Add request domain tests and factories --- tests/conftest.py | 25 +++++++++++++++- tests/domain/__init__.py | 0 tests/domain/test_requests.py | 55 +++++++++++++++++++++++++++++++++++ tests/factories.py | 11 +++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/domain/__init__.py create mode 100644 tests/domain/test_requests.py create mode 100644 tests/factories.py diff --git a/tests/conftest.py b/tests/conftest.py index c650b5f1..baafaeda 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,18 +1,21 @@ import pytest +from sqlalchemy.orm import sessionmaker, scoped_session from atst.app import make_app, make_deps, make_config +from atst.database import make_db from tests.mocks import MockApiClient, MockFundzClient, MockRequestsClient, MockAuthzClient from atst.sessions import DictSessions @pytest.fixture -def app(): +def app(db): TEST_DEPS = { "authz_client": MockAuthzClient("authz"), "requests_client": MockRequestsClient("requests"), "authnid_client": MockApiClient("authnid"), "fundz_client": MockFundzClient("fundz"), "sessions": DictSessions(), + "db_session": db } config = make_config() @@ -21,6 +24,26 @@ def app(): return make_app(config, deps) + +@pytest.fixture(scope='function') +def db(): + + # Override db with a new SQLAlchemy session so that we can rollback + # each test's transaction. + # Inspiration: https://docs.sqlalchemy.org/en/latest/orm/session_transaction.html#session-external-transaction + config = make_config() + database = make_db(config) + connection = database.get_bind().connect() + transaction = connection.begin() + db = scoped_session(sessionmaker(bind=connection)) + + yield db + + db.close() + transaction.rollback() + connection.close() + + class DummyForm(dict): pass diff --git a/tests/domain/__init__.py b/tests/domain/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/domain/test_requests.py b/tests/domain/test_requests.py new file mode 100644 index 00000000..f45d5be2 --- /dev/null +++ b/tests/domain/test_requests.py @@ -0,0 +1,55 @@ +import pytest +from uuid import uuid4 + +from atst.domain.exceptions import NotFoundError +from atst.domain.requests import Requests + +from tests.factories import RequestFactory + + +@pytest.fixture() +def requests(db): + return Requests(db) + +@pytest.fixture(scope="function") +def new_request(db): + created_request = RequestFactory.create() + db.add(created_request) + db.commit() + + return created_request + + +def test_can_get_request(requests, new_request): + request = requests.get(new_request.id) + + assert request.id == new_request.id + + +def test_nonexistent_request_raises(requests): + with pytest.raises(NotFoundError): + requests.get(uuid4()) + + +@pytest.mark.gen_test +def test_auto_approve_less_than_1m(requests, new_request): + new_request.body = {"details_of_use": {"dollar_value": 999999}} + request = yield requests.submit(new_request) + + assert request.status == 'approved' + + +@pytest.mark.gen_test +def test_dont_auto_approve_if_dollar_value_is_1m_or_above(requests, new_request): + new_request.body = {"details_of_use": {"dollar_value": 1000000}} + request = yield requests.submit(new_request) + + assert request.status == 'submitted' + + +@pytest.mark.gen_test +def test_dont_auto_approve_if_no_dollar_value_specified(requests, new_request): + new_request.body = {"details_of_use": {}} + request = yield requests.submit(new_request) + + assert request.status == 'submitted' diff --git a/tests/factories.py b/tests/factories.py new file mode 100644 index 00000000..b07b36fa --- /dev/null +++ b/tests/factories.py @@ -0,0 +1,11 @@ +import factory +from uuid import uuid4 + +from atst.models import Request, RequestStatusEvent + + +class RequestFactory(factory.Factory): + class Meta: + model = Request + + id = factory.Sequence(lambda x: uuid4()) From 373463bf37f6fc377b74f42f73a2a541ea6559c2 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Jul 2018 16:44:39 -0400 Subject: [PATCH 026/173] update tests, remove MockRequestsClient --- tests/conftest.py | 3 +-- tests/handlers/test_request_new.py | 9 +++++++++ tests/mocks.py | 23 ----------------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index baafaeda..a0ed8550 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import sessionmaker, scoped_session from atst.app import make_app, make_deps, make_config from atst.database import make_db -from tests.mocks import MockApiClient, MockFundzClient, MockRequestsClient, MockAuthzClient +from tests.mocks import MockApiClient, MockFundzClient, MockAuthzClient from atst.sessions import DictSessions @@ -11,7 +11,6 @@ from atst.sessions import DictSessions def app(db): TEST_DEPS = { "authz_client": MockAuthzClient("authz"), - "requests_client": MockRequestsClient("requests"), "authnid_client": MockApiClient("authnid"), "fundz_client": MockFundzClient("fundz"), "sessions": DictSessions(), diff --git a/tests/handlers/test_request_new.py b/tests/handlers/test_request_new.py index dfa57cab..8409fc13 100644 --- a/tests/handlers/test_request_new.py +++ b/tests/handlers/test_request_new.py @@ -3,8 +3,17 @@ import pytest import tornado import urllib from tests.mocks import MOCK_USER +from tests.factories import RequestFactory ERROR_CLASS = "alert--error" +MOCK_REQUEST = RequestFactory.create( + creator=MOCK_USER["id"], + body={ + "financial_verification": { + "pe_id": "0203752A", + }, + } +) @pytest.mark.gen_test def test_submit_invalid_request_form(monkeypatch, http_client, base_url): diff --git a/tests/mocks.py b/tests/mocks.py index a7290a03..105824f7 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -51,31 +51,8 @@ class MockApiClient(ApiClient): return response -MOCK_REQUEST = { - "id": "66b8ef71-86d3-48ef-abc2-51bfa1732b6b", - "creator": "49903ae7-da4a-49bf-a6dc-9dff5d004238", - "body": { - "financial_verification": { - "pe_id": "0203752A", - }, - }, - "status": "incomplete" -} - -class MockRequestsClient(MockApiClient): - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return self._get_response("GET", path, 200, json=MOCK_REQUEST) - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return self._get_response("POST", path, 202, json=MOCK_REQUEST) - - MOCK_VALID_PE_ID = "8675309U" - class MockFundzClient(MockApiClient): @tornado.gen.coroutine From 5f2ffe57b8da5d3611d7901751d61f79b724f34c Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 27 Jul 2018 14:57:59 -0400 Subject: [PATCH 027/173] update submodule --- script/include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include b/script/include index 7417942f..8597f54c 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 7417942f1614d6a7ad94e94d1621dca9b422dec2 +Subproject commit 8597f54c69dc1eb04c53a2fc487ebd7f8c8e648f From 0179a228271f1364a339bc234b5a8c3be3acb926 Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 27 Jul 2018 15:15:44 -0400 Subject: [PATCH 028/173] update and fix some tests from rebase --- atst/handlers/request_new.py | 1 + script/update | 7 +++-- tests/handlers/test_financial_verification.py | 2 +- tests/handlers/test_request_new.py | 1 - tests/handlers/test_request_submit.py | 30 ++++++++++++------- tests/mocks.py | 9 ++++++ 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 49454874..e43e6ab3 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -6,6 +6,7 @@ from atst.forms.request import RequestForm from atst.forms.org import OrgForm from atst.forms.poc import POCForm from atst.forms.review import ReviewForm +from atst.domain.requests import Requests class RequestNew(BaseHandler): diff --git a/script/update b/script/update index 8cb772c1..1baef9a8 100755 --- a/script/update +++ b/script/update @@ -4,5 +4,8 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Run the bootstrap script -source ./script/bootstrap +# Enable DB migration +MIGRATE_DB="true" + +# Run the shared update script +source ./script/include/run_update diff --git a/tests/handlers/test_financial_verification.py b/tests/handlers/test_financial_verification.py index 6e60bb4e..234c8d57 100644 --- a/tests/handlers/test_financial_verification.py +++ b/tests/handlers/test_financial_verification.py @@ -40,7 +40,7 @@ class TestPENumberInForm: @tornado.gen.coroutine def submit_data(self, http_client, base_url, data): response = yield http_client.fetch( - base_url + "/requests/verify/{}".format(MOCK_REQUEST["id"]), + base_url + "/requests/verify/{}".format(MOCK_REQUEST.id), method="POST", headers={"Content-Type": "application/x-www-form-urlencoded"}, body=urllib.parse.urlencode(data), diff --git a/tests/handlers/test_request_new.py b/tests/handlers/test_request_new.py index 8409fc13..3373c867 100644 --- a/tests/handlers/test_request_new.py +++ b/tests/handlers/test_request_new.py @@ -3,7 +3,6 @@ import pytest import tornado import urllib from tests.mocks import MOCK_USER -from tests.factories import RequestFactory ERROR_CLASS = "alert--error" MOCK_REQUEST = RequestFactory.create( diff --git a/tests/handlers/test_request_submit.py b/tests/handlers/test_request_submit.py index 0f60c1a1..635ff157 100644 --- a/tests/handlers/test_request_submit.py +++ b/tests/handlers/test_request_submit.py @@ -1,19 +1,26 @@ import pytest +import tornado from tests.mocks import MOCK_USER +from tests.factories import RequestFactory + + +@tornado.gen.coroutine +def _mock_func(*args, **kwargs): + return RequestFactory.create() -ERROR_CLASS = "usa-input-error-message" -APPROVED_MOCK_REQUEST = { - "status": "approved" -} @pytest.mark.gen_test def test_submit_reviewed_request(monkeypatch, http_client, base_url): monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.get_current_user", lambda s: MOCK_USER + "atst.handlers.request_submit.RequestsSubmit.get_current_user", + lambda s: MOCK_USER, ) monkeypatch.setattr( "atst.handlers.request_submit.RequestsSubmit.check_xsrf_cookie", lambda s: True ) + monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func) + monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func) + monkeypatch.setattr("atst.models.request.Request.status", "pending") # this just needs to send a known invalid form value response = yield http_client.fetch( base_url + "/requests/submit/1", @@ -21,7 +28,7 @@ def test_submit_reviewed_request(monkeypatch, http_client, base_url): headers={"Content-Type": "application/x-www-form-urlencoded"}, body="", raise_error=False, - follow_redirects=False + follow_redirects=False, ) assert response.headers["Location"] == "/requests" @@ -29,14 +36,15 @@ def test_submit_reviewed_request(monkeypatch, http_client, base_url): @pytest.mark.gen_test def test_submit_autoapproved_reviewed_request(monkeypatch, http_client, base_url): monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.get_current_user", lambda s: MOCK_USER + "atst.handlers.request_submit.RequestsSubmit.get_current_user", + lambda s: MOCK_USER, ) monkeypatch.setattr( "atst.handlers.request_submit.RequestsSubmit.check_xsrf_cookie", lambda s: True ) - monkeypatch.setattr( - "tests.mocks.MOCK_REQUEST", APPROVED_MOCK_REQUEST - ) + monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func) + monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func) + monkeypatch.setattr("atst.models.request.Request.status", "approved") # this just needs to send a known invalid form value response = yield http_client.fetch( base_url + "/requests/submit/1", @@ -44,6 +52,6 @@ def test_submit_autoapproved_reviewed_request(monkeypatch, http_client, base_url headers={"Content-Type": "application/x-www-form-urlencoded"}, body="", raise_error=False, - follow_redirects=False + follow_redirects=False, ) assert response.headers["Location"] == "/requests?modal=True" diff --git a/tests/mocks.py b/tests/mocks.py index 105824f7..96c22e4a 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -2,6 +2,7 @@ import tornado.gen from tornado.httpclient import HTTPRequest, HTTPResponse from atst.api_client import ApiClient +from tests.factories import RequestFactory MOCK_USER = { @@ -10,6 +11,14 @@ MOCK_USER = { "first_name": "Fake", "last_name": "User", } +MOCK_REQUEST = RequestFactory.create( + creator=MOCK_USER["id"], + body={ + "financial_verification": { + "pe_id": "0203752A", + }, + } +) class MockApiClient(ApiClient): From 54f2a0dce0b8406823930ab9ac56a12c166d2329 Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 27 Jul 2018 15:27:50 -0400 Subject: [PATCH 029/173] update financial verification to use requests repo --- atst/app.py | 2 +- .../request_financial_verification.py | 49 ++++++++----------- tests/handlers/test_financial_verification.py | 3 +- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/atst/app.py b/atst/app.py index 922b2ca7..c56ea250 100644 --- a/atst/app.py +++ b/atst/app.py @@ -107,7 +107,7 @@ def make_app(config, deps, **kwargs): RequestFinancialVerification, { "page": "financial_verification", - "requests_client": deps["requests_client"], + "db_session": deps["db_session"], "fundz_client": deps["fundz_client"], }, name="financial_verification", diff --git a/atst/handlers/request_financial_verification.py b/atst/handlers/request_financial_verification.py index 4c81f9d7..a063692c 100644 --- a/atst/handlers/request_financial_verification.py +++ b/atst/handlers/request_financial_verification.py @@ -2,26 +2,23 @@ import tornado from atst.handler import BaseHandler from atst.forms.financial import FinancialForm +from atst.domain.requests import Requests class RequestFinancialVerification(BaseHandler): - def initialize(self, page, requests_client, fundz_client): + def initialize(self, page, db_session, fundz_client): self.page = page - self.requests_client = requests_client + self.requests_repo = Requests(db_session) self.fundz_client = fundz_client - @tornado.gen.coroutine def get_existing_request(self, request_id): - if request_id is None: - return {} - request = yield self.requests_client.get("/requests/{}".format(request_id)) - return request.json + return self.requests_repo.get(request_id) @tornado.web.authenticated @tornado.gen.coroutine def get(self, request_id=None): - existing_request = yield self.get_existing_request(request_id) - form = FinancialForm(data=existing_request['body'].get('financial_verification')) + existing_request = self.get_existing_request(request_id) + form = FinancialForm(data=existing_request.body.get('financial_verification')) self.render( "requests/financial_verification.html.to", page=self.page, @@ -35,39 +32,33 @@ class RequestFinancialVerification(BaseHandler): "creator_id": self.current_user["id"], "request": {"financial_verification": form_data}, } - response = yield self.requests_client.patch( - "/requests/{}".format(request_id), json=request_data - ) - return response + return self.requests_repo.update(request_id, request_data) @tornado.web.authenticated @tornado.gen.coroutine def post(self, request_id=None): self.check_xsrf_cookie() post_data = self.request.arguments - existing_request = yield self.get_existing_request(request_id) + existing_request = self.get_existing_request(request_id) form = FinancialForm(post_data) rerender_args = dict(request_id=request_id, f=form) if form.validate(): - response = yield self.update_request(request_id, form.data) - if response.ok: - valid = yield form.perform_extra_validation( - existing_request.get('body', {}).get('financial_verification'), - self.fundz_client + yield self.update_request(request_id, form.data) + valid = yield form.perform_extra_validation( + existing_request.body.get('financial_verification'), + self.fundz_client + ) + if valid: + self.redirect( + self.application.default_router.reverse_url("financial_verification_submitted") ) - if valid: - self.redirect( - self.application.default_router.reverse_url("financial_verification_submitted") - ) - else: - self.render( - "requests/financial_verification.html.to", - **rerender_args - ) else: - self.set_status(response.code) + self.render( + "requests/financial_verification.html.to", + **rerender_args + ) else: self.render( "requests/financial_verification.html.to", diff --git a/tests/handlers/test_financial_verification.py b/tests/handlers/test_financial_verification.py index 234c8d57..57b8851d 100644 --- a/tests/handlers/test_financial_verification.py +++ b/tests/handlers/test_financial_verification.py @@ -36,6 +36,7 @@ class TestPENumberInForm: "atst.handlers.request_financial_verification.RequestFinancialVerification.check_xsrf_cookie", lambda s: True ) monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True) + monkeypatch.setattr("atst.domain.requests.Requests.get", lambda s, i: MOCK_REQUEST) @tornado.gen.coroutine def submit_data(self, http_client, base_url, data): @@ -64,7 +65,7 @@ class TestPENumberInForm: self._set_monkeypatches(monkeypatch) data = dict(self.required_data) - data['pe_id'] = MOCK_REQUEST['body']['financial_verification']['pe_id'] + data['pe_id'] = MOCK_REQUEST.body['financial_verification']['pe_id'] response = yield self.submit_data(http_client, base_url, data) From 3bd1efcd03d558e261899fdeb91482d9ee6d3f35 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 10:15:48 -0400 Subject: [PATCH 030/173] add new config pattern for database URI and overrides --- atst/app.py | 55 ++++++++++++++++++++++++++++++++++++------------- config/base.ini | 6 +++++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/atst/app.py b/atst/app.py index c56ea250..73e144fc 100644 --- a/atst/app.py +++ b/atst/app.py @@ -24,6 +24,7 @@ from atst.database import make_db ENV = os.getenv("TORNADO_ENV", "dev") + def make_app(config, deps, **kwargs): routes = [ @@ -31,16 +32,15 @@ def make_app(config, deps, **kwargs): url( r"/login-redirect", LoginRedirect, - {"sessions": deps["sessions"], "authnid_client": deps["authnid_client"], "authz_client": deps["authz_client"]}, + { + "sessions": deps["sessions"], + "authnid_client": deps["authnid_client"], + "authz_client": deps["authz_client"], + }, name="login_redirect", ), url(r"/home", Main, {"page": "home"}, name="home"), - url( - r"/styleguide", - Main, - {"page": "styleguide"}, - name="styleguide", - ), + url(r"/styleguide", Main, {"page": "styleguide"}, name="styleguide"), url( r"/workspaces/blank", Main, @@ -100,7 +100,7 @@ def make_app(config, deps, **kwargs): r"/request/approval", Main, {"page": "request_approval"}, - name="request_approval" + name="request_approval", ), url( r"/requests/verify/(\S+)", @@ -121,7 +121,9 @@ def make_app(config, deps, **kwargs): url(r"/users", Main, {"page": "users"}, name="users"), url(r"/reports", Main, {"page": "reports"}, name="reports"), url(r"/calculator", Main, {"page": "calculator"}, name="calculator"), - url(r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members"), + url( + r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members" + ), url(r"/workspaces/(\S+)/projects", Workspace, {}, name="workspace_projects"), url(r"/workspaces/123456/projects/789/edit", Main, {"page": "project_edit"}, name="project_edit"), url(r"/workspaces/123456/members/789/edit", Main, {"page": "member_edit"}, name="member_edit"), @@ -132,7 +134,11 @@ def make_app(config, deps, **kwargs): url( r"/login-dev", Dev, - {"action": "login", "sessions": deps["sessions"], "authz_client": deps["authz_client"]}, + { + "action": "login", + "sessions": deps["sessions"], + "authz_client": deps["authz_client"], + }, name="dev-login", ) ] @@ -146,7 +152,7 @@ def make_app(config, deps, **kwargs): debug=config["default"].getboolean("DEBUG"), ui_modules=ui_modules, ui_methods=ui_methods, - **kwargs, + **kwargs ) app.config = config app.sessions = deps["sessions"] @@ -173,8 +179,7 @@ def make_deps(config): validate_cert=validate_cert, ), "fundz_client": ApiClient( - config["default"]["FUNDZ_BASE_URL"], - validate_cert=validate_cert, + config["default"]["FUNDZ_BASE_URL"], validate_cert=validate_cert ), "requests_client": ApiClient( config["default"]["REQUESTS_QUEUE_BASE_URL"], @@ -192,8 +197,30 @@ def make_config(): ENV_CONFIG_FILENAME = os.path.join( os.path.dirname(__file__), "../config/", "{}.ini".format(ENV.lower()) ) + OVERRIDE_CONFIG_FILENAME = os.getenv("OVERRIDE_CONFIG_FULLPATH") + config = ConfigParser() + config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME] + if OVERRIDE_CONFIG_FILENAME: + config_files.append(OVERRIDE_CONFIG_FILENAME) + # ENV_CONFIG will override values in BASE_CONFIG. - config.read([BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME]) + config.read(config_files) + + # Assemble DATABASE_URI value + database_uri = ( + "postgres://" + + config.get("default", "DATABASE_USERNAME") + + ":" + + config.get("default", "DATABASE_PASSWORD") + + "@" + + config.get("default", "DATABASE_HOST") + + ":" + + config.get("default", "DATABASE_PORT") + + "/" + + config.get("default", "DATABASE_NAME") + ) + config.set("default", "DATABASE_URI", database_uri) + return config diff --git a/config/base.ini b/config/base.ini index 8b6e68a2..92f40d5a 100644 --- a/config/base.ini +++ b/config/base.ini @@ -11,4 +11,8 @@ CAC_URL = https://localhost:8001 REQUESTS_QUEUE_BASE_URL = http://localhost:8003 REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 -DATABASE_URI = postgres://postgres:postgres@localhost/atat +DATABASE_HOST = localhost +DATABASE_PORT = 5432 +DATABASE_USERNAME = postgres +DATABASE_PASSWORD = postgres +DATABASE_NAME = atat From b5055c8ce899c59a0179001b21661fc557b5c06c Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 15:50:50 -0400 Subject: [PATCH 031/173] Change db vars to standard postgres equivalents --- atst/app.py | 10 +++++----- config/base.ini | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/atst/app.py b/atst/app.py index 73e144fc..efc649b3 100644 --- a/atst/app.py +++ b/atst/app.py @@ -211,15 +211,15 @@ def make_config(): # Assemble DATABASE_URI value database_uri = ( "postgres://" - + config.get("default", "DATABASE_USERNAME") + + config.get("default", "PGUSER") + ":" - + config.get("default", "DATABASE_PASSWORD") + + config.get("default", "PGPASSWORD") + "@" - + config.get("default", "DATABASE_HOST") + + config.get("default", "PGHOST") + ":" - + config.get("default", "DATABASE_PORT") + + config.get("default", "PGPORT") + "/" - + config.get("default", "DATABASE_NAME") + + config.get("default", "PGDATABASE") ) config.set("default", "DATABASE_URI", database_uri) diff --git a/config/base.ini b/config/base.ini index 92f40d5a..6e6af123 100644 --- a/config/base.ini +++ b/config/base.ini @@ -11,8 +11,8 @@ CAC_URL = https://localhost:8001 REQUESTS_QUEUE_BASE_URL = http://localhost:8003 REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 -DATABASE_HOST = localhost -DATABASE_PORT = 5432 -DATABASE_USERNAME = postgres -DATABASE_PASSWORD = postgres -DATABASE_NAME = atat +PGHOST = localhost +PGPORT = 5432 +PGUSER = postgres +PGPASSWORD = postgres +PGDATABASE = atat From 6e9d8f92c4e392fcf5ac3de9a543b1c691693260 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 15:51:36 -0400 Subject: [PATCH 032/173] Add wrapper script for settign DB ENV vars --- script/get_db_settings.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100755 script/get_db_settings.sh diff --git a/script/get_db_settings.sh b/script/get_db_settings.sh new file mode 100755 index 00000000..7b30fd7b --- /dev/null +++ b/script/get_db_settings.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# script/get_db_settings: Fetch postgresql settings and set them as ENV vars + +source "$(dirname "${0}")"/../script/include/global_header.inc.sh + +# Run the shared get_db_settings script +source ./script/include/run_get_sb_settings.sh From 7f09be55912552cf054ea84f59f771e66bc8ff82 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 15:51:55 -0400 Subject: [PATCH 033/173] Switch to scriptz feature branch --- script/include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include b/script/include index 8597f54c..cb8cbe46 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 8597f54c69dc1eb04c53a2fc487ebd7f8c8e648f +Subproject commit cb8cbe46d0e8171fcd497e4d22ab719692347562 From d22f85508bdb16c083733080f4b6849587c16828 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 18:22:08 -0400 Subject: [PATCH 034/173] Add postgres hostname used during CI --- config/ci.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/ci.ini b/config/ci.ini index e69de29b..0469ae77 100644 --- a/config/ci.ini +++ b/config/ci.ini @@ -0,0 +1,2 @@ +[default] +PGHOST = travishost From 168bee20f8b7efb4050aa780ba9f515b87a39c60 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 18:22:42 -0400 Subject: [PATCH 035/173] Add postgres to ATST build - Add postgres 9.6 service - Add Travis host IP entry to docker container --- .travis.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02dab0db..0b452ab2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,11 @@ sudo: required language: python python: "3.6" -services: docker +services: + - docker + - postgres +addons: + postgresql: "9.6" git: submodules: false env: @@ -16,8 +20,9 @@ before_install: - git submodule update --init --recursive before_script: + - travis_host_ip="$(/sbin/ip route|awk '/default/ { print $3 }')" - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - - docker build --tag "${TESTER_IMAGE_NAME}" . -f deploy/docker/tester/Dockerfile + - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "travishost:${travis_host_ip}" . -f deploy/docker/tester/Dockerfile script: - docker run "${TESTER_IMAGE_NAME}" From abb16ec39798c47664c83e45d7f71e3b6712853e Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 18:26:53 -0400 Subject: [PATCH 036/173] Add DB info and setup --- script/setup | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/setup b/script/setup index 925ced94..5cd11461 100755 --- a/script/setup +++ b/script/setup @@ -8,5 +8,11 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Turn on sass compiler installation INSTALL_SASS="true" +# Set database name +DATABASE_NAME="atat" + +# Enable database resetting +RESET_DB="true" + # Run the shared setup script source ./script/include/run_setup From 1875dbc9fdfb1b53a096712e086a30ff612a05e9 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 18:31:18 -0400 Subject: [PATCH 037/173] Rename script --- script/{get_db_settings.sh => get_db_settings} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename script/{get_db_settings.sh => get_db_settings} (100%) diff --git a/script/get_db_settings.sh b/script/get_db_settings similarity index 100% rename from script/get_db_settings.sh rename to script/get_db_settings From 9cb5bee363a1e24f7bbbe082f981a1ab00d37deb Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 18:41:01 -0400 Subject: [PATCH 038/173] Fix type --- script/get_db_settings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/get_db_settings b/script/get_db_settings index 7b30fd7b..c96970a8 100755 --- a/script/get_db_settings +++ b/script/get_db_settings @@ -5,4 +5,4 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run the shared get_db_settings script -source ./script/include/run_get_sb_settings.sh +source ./script/include/run_get_db_settings.sh From a2b893830f9d0b27566a0b58b90013f8d31f1b6c Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 19:50:33 -0400 Subject: [PATCH 039/173] Remove blank line --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6089986f..455d5baa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # ATST [![Build Status](https://travis-ci.org/dod-ccpo/atst.svg?branch=master)](https://travis-ci.org/dod-ccpo/atst) From 3dcdcdfb3b39cb976eaaf8ed38ec86d94394466a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 20:02:41 -0400 Subject: [PATCH 040/173] Debug travis ip and psql connect issues --- .travis.yml | 3 +++ script/get_db_settings | 3 +++ script/setup | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0b452ab2..37b0fa76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,9 @@ before_install: - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules # Manually initialize submodules - git submodule update --init --recursive + - /sbin/ip route|awk '/default/ { print $3 }' + - /sbin/ip addr + - ./foo before_script: - travis_host_ip="$(/sbin/ip route|awk '/default/ { print $3 }')" diff --git a/script/get_db_settings b/script/get_db_settings index c96970a8..2c60ec3c 100755 --- a/script/get_db_settings +++ b/script/get_db_settings @@ -6,3 +6,6 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run the shared get_db_settings script source ./script/include/run_get_db_settings.sh + +echo "Postgres settings: " +echo $PGHOST diff --git a/script/setup b/script/setup index 5cd11461..c64ff07a 100755 --- a/script/setup +++ b/script/setup @@ -14,5 +14,8 @@ DATABASE_NAME="atat" # Enable database resetting RESET_DB="true" +echo "Hosts file:" +cat /etc/hosts + # Run the shared setup script source ./script/include/run_setup From 23fbc33f5d00b3dac30ab37616ea6df14c8540e3 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 20:05:50 -0400 Subject: [PATCH 041/173] Debug travis ip and psql connect issues --- .travis.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 37b0fa76..311e93ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,15 +14,15 @@ env: - PROD_IMAGE_NAME=atst-prod before_install: - # Use sed to replace the SSH URL with the public URL - - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules - # Manually initialize submodules - - git submodule update --init --recursive - - /sbin/ip route|awk '/default/ { print $3 }' - - /sbin/ip addr - - ./foo + # Use sed to replace the SSH URL with the public URL + - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules + # Manually initialize submodules + - git submodule update --init --recursive + - /sbin/ip route|awk '/default/ { print $3 }' + - /sbin/ip addr before_script: + - netstat -anlp | grep LISTEN | grep tcp - travis_host_ip="$(/sbin/ip route|awk '/default/ { print $3 }')" - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "travishost:${travis_host_ip}" . -f deploy/docker/tester/Dockerfile From f7adeb5af327597dda62271720b03461c96534e8 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 20:19:36 -0400 Subject: [PATCH 042/173] Ensure get_db is sourced so the vars carry over --- script/get_db_settings | 5 ++++- script/include | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/script/get_db_settings b/script/get_db_settings index 2c60ec3c..701c2844 100755 --- a/script/get_db_settings +++ b/script/get_db_settings @@ -7,5 +7,8 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run the shared get_db_settings script source ./script/include/run_get_db_settings.sh +echo echo "Postgres settings: " -echo $PGHOST +echo "PGHOST: $PGHOST" +echo "PGDATABASE: $PGDATABASE" +echo diff --git a/script/include b/script/include index cb8cbe46..5c19aef7 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit cb8cbe46d0e8171fcd497e4d22ab719692347562 +Subproject commit 5c19aef7482aa0035f2d85e4c30ee21dfd7969c9 From ab3ba06f18643163d3bda841ca60d3df268e1ce8 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 20:25:01 -0400 Subject: [PATCH 043/173] Ensure app env is ci when testing --- deploy/docker/tester/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/docker/tester/Dockerfile b/deploy/docker/tester/Dockerfile index c490c6ec..bfec5729 100644 --- a/deploy/docker/tester/Dockerfile +++ b/deploy/docker/tester/Dockerfile @@ -8,7 +8,9 @@ ARG APP_DIR=/opt/atat/atst ARG CIBUILD=true ENV APP_DIR "${APP_DIR}" +ENV FLASK_ENV ci ENV SKIP_PIPENV true +ENV TORNADO_ENV ci # Use dumb-init for proper signal handling ENTRYPOINT ["/usr/bin/dumb-init", "--"] From c551e02c2ee3db6318b58c6243608fdbdd0a3edb Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 30 Jul 2018 20:35:00 -0400 Subject: [PATCH 044/173] Add app name to PG settings --- config/base.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/config/base.ini b/config/base.ini index 6e6af123..6f63d78f 100644 --- a/config/base.ini +++ b/config/base.ini @@ -11,6 +11,7 @@ CAC_URL = https://localhost:8001 REQUESTS_QUEUE_BASE_URL = http://localhost:8003 REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 +PGAPPNAME = atst PGHOST = localhost PGPORT = 5432 PGUSER = postgres From f6d6865bb3ac9727db2fd0be456dd62898cb43cf Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 31 Jul 2018 06:26:25 -0400 Subject: [PATCH 045/173] Switch to postgres in a container --- .travis.yml | 10 ++++------ config/ci.ini | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 311e93ce..3d76a657 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,6 @@ language: python python: "3.6" services: - docker - - postgres -addons: - postgresql: "9.6" git: submodules: false env: @@ -22,10 +19,11 @@ before_install: - /sbin/ip addr before_script: - - netstat -anlp | grep LISTEN | grep tcp - - travis_host_ip="$(/sbin/ip route|awk '/default/ { print $3 }')" + - docker run -d --name postgres96 postgres:9.6-alpine + - docker run --link postgres96:postgres96 waisbrot/wait + - postgres_ip="$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" postgres96)" - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "travishost:${travis_host_ip}" . -f deploy/docker/tester/Dockerfile + - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "postgreshost:${postgres_ip}" . -f deploy/docker/tester/Dockerfile script: - docker run "${TESTER_IMAGE_NAME}" diff --git a/config/ci.ini b/config/ci.ini index 0469ae77..3796c0a7 100644 --- a/config/ci.ini +++ b/config/ci.ini @@ -1,2 +1,2 @@ [default] -PGHOST = travishost +PGHOST = postgreshost From baed8492291e53c408c26c64b2cd3256bb450b1e Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 31 Jul 2018 06:37:26 -0400 Subject: [PATCH 046/173] Add postgres host to running container --- .travis.yml | 4 ++-- script/cibuild | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d76a657..479a8955 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,12 +21,12 @@ before_install: before_script: - docker run -d --name postgres96 postgres:9.6-alpine - docker run --link postgres96:postgres96 waisbrot/wait - - postgres_ip="$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" postgres96)" + - export postgres_ip="$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" postgres96)" - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "postgreshost:${postgres_ip}" . -f deploy/docker/tester/Dockerfile script: - - docker run "${TESTER_IMAGE_NAME}" + - docker run --add-host "postgreshost:${postgres_ip}" "${TESTER_IMAGE_NAME}" before_deploy: - docker build --tag "${PROD_IMAGE_NAME}" . -f deploy/docker/prod/Dockerfile diff --git a/script/cibuild b/script/cibuild index e9d01564..387f61b8 100755 --- a/script/cibuild +++ b/script/cibuild @@ -4,5 +4,10 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh +echo +echo "DEBUG: Hosts file:" +cat /etc/hosts +echo + # Run lint/style checks and unit tests source ./script/test From 07db14e9520ce83e61f7ae6d18cba7ccdd9e4444 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 31 Jul 2018 07:03:49 -0400 Subject: [PATCH 047/173] Remove debugging related items --- .travis.yml | 2 -- script/cibuild | 5 ----- script/get_db_settings | 6 ------ script/setup | 3 --- 4 files changed, 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 479a8955..49883310 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,6 @@ before_install: - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules # Manually initialize submodules - git submodule update --init --recursive - - /sbin/ip route|awk '/default/ { print $3 }' - - /sbin/ip addr before_script: - docker run -d --name postgres96 postgres:9.6-alpine diff --git a/script/cibuild b/script/cibuild index 387f61b8..e9d01564 100755 --- a/script/cibuild +++ b/script/cibuild @@ -4,10 +4,5 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh -echo -echo "DEBUG: Hosts file:" -cat /etc/hosts -echo - # Run lint/style checks and unit tests source ./script/test diff --git a/script/get_db_settings b/script/get_db_settings index 701c2844..c96970a8 100755 --- a/script/get_db_settings +++ b/script/get_db_settings @@ -6,9 +6,3 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run the shared get_db_settings script source ./script/include/run_get_db_settings.sh - -echo -echo "Postgres settings: " -echo "PGHOST: $PGHOST" -echo "PGDATABASE: $PGDATABASE" -echo diff --git a/script/setup b/script/setup index c64ff07a..5cd11461 100755 --- a/script/setup +++ b/script/setup @@ -14,8 +14,5 @@ DATABASE_NAME="atat" # Enable database resetting RESET_DB="true" -echo "Hosts file:" -cat /etc/hosts - # Run the shared setup script source ./script/include/run_setup From 945eee9a6fa32b3ca3df5c5826111224cce93162 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 31 Jul 2018 08:47:57 -0400 Subject: [PATCH 048/173] Update to most recent scriptz --- script/include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include b/script/include index 5c19aef7..90a453b2 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 5c19aef7482aa0035f2d85e4c30ee21dfd7969c9 +Subproject commit 90a453b2ac4272961b3ed5f7d77d60816a09e092 From 9c153e0772a0dea98b3002c921555d16c5e1d268 Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 08:49:00 -0400 Subject: [PATCH 049/173] fix lint errors --- atst/domain/workspaces.py | 3 --- atst/handlers/request_new.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/atst/domain/workspaces.py b/atst/domain/workspaces.py index ca848425..b4cc85b8 100644 --- a/atst/domain/workspaces.py +++ b/atst/domain/workspaces.py @@ -1,6 +1,3 @@ -import tornado.gen - - class Projects(object): def __init__(self): diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index e43e6ab3..67c24585 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -50,7 +50,7 @@ class RequestNew(BaseHandler): ) if jedi_flow.validate(): - request = jedi_flow.create_or_update_request() + jedi_flow.create_or_update_request() valid = yield jedi_flow.validate_warnings() if valid: if jedi_flow.next_screen > len(jedi_flow.screens): From 432fb67506b973b89e6586aeb775c4a6792b07fc Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 09:35:17 -0400 Subject: [PATCH 050/173] remove references to requests-queue url and client --- atst/app.py | 5 ----- config/base.ini | 1 - 2 files changed, 6 deletions(-) diff --git a/atst/app.py b/atst/app.py index efc649b3..a488b4bf 100644 --- a/atst/app.py +++ b/atst/app.py @@ -181,11 +181,6 @@ def make_deps(config): "fundz_client": ApiClient( config["default"]["FUNDZ_BASE_URL"], validate_cert=validate_cert ), - "requests_client": ApiClient( - config["default"]["REQUESTS_QUEUE_BASE_URL"], - api_version="v1", - validate_cert=validate_cert, - ), "sessions": RedisSessions( redis_client, config["default"]["SESSION_TTL_SECONDS"] ), diff --git a/config/base.ini b/config/base.ini index 6f63d78f..78d56c36 100644 --- a/config/base.ini +++ b/config/base.ini @@ -8,7 +8,6 @@ FUNDZ_BASE_URL= http://localhost:8004 COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret CAC_URL = https://localhost:8001 -REQUESTS_QUEUE_BASE_URL = http://localhost:8003 REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 PGAPPNAME = atst From c1fdde4ab79030be6abb39b80a17bb2386214812 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 11:36:03 -0400 Subject: [PATCH 051/173] import authz models --- .../versions/4ede1e3e50d1_add_authz_models.py | 62 +++++++++++++++++++ atst/models/__init__.py | 4 ++ atst/models/permissions.py | 40 ++++++++++++ atst/models/role.py | 14 +++++ atst/models/user.py | 21 +++++++ atst/models/workspace_role.py | 24 +++++++ 6 files changed, 165 insertions(+) create mode 100644 alembic/versions/4ede1e3e50d1_add_authz_models.py create mode 100644 atst/models/permissions.py create mode 100644 atst/models/role.py create mode 100644 atst/models/user.py create mode 100644 atst/models/workspace_role.py diff --git a/alembic/versions/4ede1e3e50d1_add_authz_models.py b/alembic/versions/4ede1e3e50d1_add_authz_models.py new file mode 100644 index 00000000..d782b676 --- /dev/null +++ b/alembic/versions/4ede1e3e50d1_add_authz_models.py @@ -0,0 +1,62 @@ +"""add_authz_models + +Revision ID: 4ede1e3e50d1 +Revises: b5b17d465166 +Create Date: 2018-07-30 11:34:12.016857 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '4ede1e3e50d1' +down_revision = 'b5b17d465166' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('roles', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('name', sa.String(), nullable=True), + sa.Column('description', sa.String(), nullable=True), + sa.Column('permissions', postgresql.ARRAY(sa.String()), server_default='{}', nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_roles_name'), 'roles', ['name'], unique=True) + op.create_index(op.f('ix_roles_permissions'), 'roles', ['permissions'], unique=False) + op.create_table('users', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('username', sa.String(), nullable=True), + sa.Column('atat_role_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.ForeignKeyConstraint(['atat_role_id'], ['roles.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('workspace_role', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('workspace_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('role_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_workspace_role_user_id'), 'workspace_role', ['user_id'], unique=False) + op.create_index(op.f('ix_workspace_role_workspace_id'), 'workspace_role', ['workspace_id'], unique=False) + op.create_index('workspace_role_user_workspace', 'workspace_role', ['user_id', 'workspace_id'], unique=True) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('workspace_role_user_workspace', table_name='workspace_role') + op.drop_index(op.f('ix_workspace_role_workspace_id'), table_name='workspace_role') + op.drop_index(op.f('ix_workspace_role_user_id'), table_name='workspace_role') + op.drop_table('workspace_role') + op.drop_table('users') + op.drop_index(op.f('ix_roles_permissions'), table_name='roles') + op.drop_index(op.f('ix_roles_name'), table_name='roles') + op.drop_table('roles') + # ### end Alembic commands ### diff --git a/atst/models/__init__.py b/atst/models/__init__.py index ef5d9457..fef82003 100644 --- a/atst/models/__init__.py +++ b/atst/models/__init__.py @@ -4,3 +4,7 @@ Base = declarative_base() from .request import Request from .request_status_event import RequestStatusEvent +from .permissions import Permissions +from .role import Role +from .user import User +from .workspace_role import WorkspaceRole diff --git a/atst/models/permissions.py b/atst/models/permissions.py new file mode 100644 index 00000000..9536348f --- /dev/null +++ b/atst/models/permissions.py @@ -0,0 +1,40 @@ +class Permissions(object): + REQUEST_JEDI_WORKSPACE = "request_jedi_workspace" + VIEW_ORIGINAL_JEDI_REQEUST = "view_original_jedi_request" + REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST = ( + "review_and_approve_jedi_workspace_request" + ) + MODIFY_ATAT_ROLE_PERMISSIONS = "modify_atat_role_permissions" + CREATE_CSP_ROLE = "create_csp_role" + DELETE_CSP_ROLE = "delete_csp_role" + DEACTIVE_CSP_ROLE = "deactivate_csp_role" + MODIFY_CSP_ROLE_PERMISSIONS = "modify_csp_role_permissions" + + VIEW_USAGE_REPORT = "view_usage_report" + VIEW_USAGE_DOLLARS = "view_usage_dollars" + ADD_AND_ASSIGN_CSP_ROLES = "add_and_assign_csp_roles" + REMOVE_CSP_ROLES = "remove_csp_roles" + REQUEST_NEW_CSP_ROLE = "request_new_csp_role" + ASSIGN_AND_UNASSIGN_ATAT_ROLE = "assign_and_unassign_atat_role" + + VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS = "view_assigned_atat_role_configurations" + VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS = "view_assigned_csp_role_configurations" + + DEACTIVATE_WORKSPACE = "deactivate_workspace" + VIEW_ATAT_PERMISSIONS = "view_atat_permissions" + TRANSFER_OWNERSHIP_OF_WORKSPACE = "transfer_ownership_of_workspace" + + ADD_APPLICATION_IN_WORKSPACE = "add_application_in_workspace" + DELETE_APPLICATION_IN_WORKSPACE = "delete_application_in_workspace" + DEACTIVATE_APPLICATION_IN_WORKSPACE = "deactivate_application_in_workspace" + VIEW_APPLICATION_IN_WORKSPACE = "view_application_in_workspace" + RENAME_APPLICATION_IN_WORKSPACE = "rename_application_in_workspace" + + ADD_ENVIRONMENT_IN_APPLICATION = "add_environment_in_application" + DELETE_ENVIRONMENT_IN_APPLICATION = "delete_environment_in_application" + DEACTIVATE_ENVIRONMENT_IN_APPLICATION = "deactivate_environment_in_application" + VIEW_ENVIRONMENT_IN_APPLICATION = "view_environment_in_application" + RENAME_ENVIRONMENT_IN_APPLICATION = "rename_environment_in_application" + + ADD_TAG_TO_WORKSPACE = "add_tag_to_workspace" + REMOVE_TAG_FROM_WORKSPACE = "remove_tag_from_workspace" diff --git a/atst/models/role.py b/atst/models/role.py new file mode 100644 index 00000000..1205dedd --- /dev/null +++ b/atst/models/role.py @@ -0,0 +1,14 @@ +from sqlalchemy import String, Column +from sqlalchemy.dialects.postgresql import ARRAY + +from atst.models import Base +from .types import Id + + +class Role(Base): + __tablename__ = "roles" + + id = Id() + name = Column(String, index=True, unique=True) + description = Column(String) + permissions = Column(ARRAY(String), index=True, server_default="{}") diff --git a/atst/models/user.py b/atst/models/user.py new file mode 100644 index 00000000..f3954f26 --- /dev/null +++ b/atst/models/user.py @@ -0,0 +1,21 @@ +from sqlalchemy import String, ForeignKey, Column +from sqlalchemy.orm import relationship +from sqlalchemy.dialects.postgresql import UUID + +from atst.models import Base +from .types import Id + + +class User(Base): + __tablename__ = "users" + + id = Id() + username = Column(String) + atat_role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id")) + + atat_role = relationship("Role") + workspace_roles = relationship("WorkspaceRole", backref="user") + + @property + def atat_permissions(self): + return self.atat_role.permissions diff --git a/atst/models/workspace_role.py b/atst/models/workspace_role.py new file mode 100644 index 00000000..86970e0b --- /dev/null +++ b/atst/models/workspace_role.py @@ -0,0 +1,24 @@ +from sqlalchemy import Index, ForeignKey, Column +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship + +from atst.models import Base +from .types import Id + + +class WorkspaceRole(Base): + __tablename__ = "workspace_role" + + id = Id() + workspace_id = Column(UUID(as_uuid=True), index=True) + role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id")) + user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True) + role = relationship("Role") + + +Index( + "workspace_role_user_workspace", + WorkspaceRole.user_id, + WorkspaceRole.workspace_id, + unique=True, +) From b4050b306efa9823ab6e7d3760bc04833ad5b938 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 11:44:56 -0400 Subject: [PATCH 052/173] import authz domain module --- atst/domain/roles.py | 19 ++++++++++ atst/domain/users.py | 58 ++++++++++++++++++++++++++++++ atst/domain/workspace_users.py | 64 ++++++++++++++++++++++++++++++++++ atst/models/workspace_user.py | 14 ++++++++ 4 files changed, 155 insertions(+) create mode 100644 atst/domain/roles.py create mode 100644 atst/domain/users.py create mode 100644 atst/domain/workspace_users.py create mode 100644 atst/models/workspace_user.py diff --git a/atst/domain/roles.py b/atst/domain/roles.py new file mode 100644 index 00000000..1b5f66c0 --- /dev/null +++ b/atst/domain/roles.py @@ -0,0 +1,19 @@ +from sqlalchemy.orm.exc import NoResultFound + +from atst.models import Role +from .exceptions import NotFoundError + + +class Roles(object): + @classmethod + def get(cls, role_name): + try: + role = Role.query.filter_by(name=role_name).one() + except NoResultFound: + raise NotFoundError("role") + + return role + + @classmethod + def get_all(cls): + return Role.query.all() diff --git a/atst/domain/users.py b/atst/domain/users.py new file mode 100644 index 00000000..ace13eb5 --- /dev/null +++ b/atst/domain/users.py @@ -0,0 +1,58 @@ +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.exc import IntegrityError + +from atst.models import User + +from .roles import Roles +from .exceptions import NotFoundError, AlreadyExistsError + + +class Users(object): + + def __init__(self, db_session): + self.db_session = db_session + + + def get(self, user_id): + try: + user = User.query.filter_by(id=user_id).one() + except NoResultFound: + raise NotFoundError("user") + + return user + + def create(self, user_id, atat_role_name): + atat_role = Roles.get(atat_role_name) + + try: + user = User(id=user_id, atat_role=atat_role) + self.db_session.add(user) + self.db_session.commit() + except IntegrityError: + raise AlreadyExistsError("user") + + return user + + def get_or_create(self, user_id, *args, **kwargs): + created = False + + try: + user = Users.get(user_id) + except NotFoundError: + user = Users.create(user_id, *args, **kwargs) + self.db_session.add(user) + self.db_session.commit() + created = True + + return user, created + + def update(self, user_id, atat_role_name): + + user = Users.get(user_id) + atat_role = Roles.get(atat_role_name) + user.atat_role = atat_role + + self.db_session.add(user) + self.db_session.commit() + + return user diff --git a/atst/domain/workspace_users.py b/atst/domain/workspace_users.py new file mode 100644 index 00000000..9ff139cd --- /dev/null +++ b/atst/domain/workspace_users.py @@ -0,0 +1,64 @@ +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.dialects.postgresql import insert + +from atst.models import User, WorkspaceRole, Role +from .exceptions import NotFoundError + +class WorkspaceUsers(object): + + def __init__(self, db_session): + self.db_session = db_session + + def get(self, workspace_id, user_id): + try: + user = User.query.filter_by(id=user_id).one() + except NoResultFound: + raise NotFoundError("user") + + try: + workspace_role = ( + WorkspaceRole.query.join(User) + .filter(User.id == user_id, WorkspaceRole.workspace_id == workspace_id) + .one() + ) + except NoResultFound: + workspace_role = None + + return WorkspaceUser(user, workspace_role) + + def add_many(self, workspace_id, workspace_user_dicts): + workspace_users = [] + + for user_dict in workspace_user_dicts: + try: + user = User.query.filter_by(id=user_dict["id"]).one() + except NoResultFound: + default_role = Role.query.filter_by(name="developer").one_or_none() + user = User(id=user_dict["id"], atat_role=default_role) + + try: + role = Role.query.filter_by(name=user_dict["workspace_role"]).one() + except NoResultFound: + raise NotFoundError("role") + + try: + existing_workspace_role = WorkspaceRole.query.filter( + WorkspaceRole.user == user, + WorkspaceRole.workspace_id == workspace_id, + ).one() + new_workspace_role = existing_workspace_role + new_workspace_role.role = role + except NoResultFound: + new_workspace_role = WorkspaceRole( + user=user, role_id=role.id, workspace_id=workspace_id + ) + + user.workspace_roles.append(new_workspace_role) + workspace_user = WorkspaceUser(user, new_workspace_role) + workspace_users.append(workspace_user) + + self.db_session.add(user) + + self.db_session.commit() + + return workspace_users diff --git a/atst/models/workspace_user.py b/atst/models/workspace_user.py new file mode 100644 index 00000000..6faba2d6 --- /dev/null +++ b/atst/models/workspace_user.py @@ -0,0 +1,14 @@ +class WorkspaceUser(object): + def __init__(self, user, workspace_role): + self.user = user + self.workspace_role = workspace_role + + def permissions(self): + atat_permissions = set(self.user.atat_role.permissions) + workspace_permissions = ( + [] if self.workspace_role is None else self.workspace_role.role.permissions + ) + return set(workspace_permissions).union(atat_permissions) + + def workspace_id(self): + return self.workspace_role.workspace_id From 25d3cbac284c8c41210075fd2cb2b957753a9ad7 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 14:03:42 -0400 Subject: [PATCH 053/173] add role and perms migrations for authorization --- .../4ea5917e7781_add_default_atat_role.py | 39 ++++ .../96a9f3537996_add_roles_and_permissions.py | 183 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 alembic/versions/4ea5917e7781_add_default_atat_role.py create mode 100644 alembic/versions/96a9f3537996_add_roles_and_permissions.py diff --git a/alembic/versions/4ea5917e7781_add_default_atat_role.py b/alembic/versions/4ea5917e7781_add_default_atat_role.py new file mode 100644 index 00000000..78b6ef55 --- /dev/null +++ b/alembic/versions/4ea5917e7781_add_default_atat_role.py @@ -0,0 +1,39 @@ +"""add_default_atat_role + +Revision ID: 4ea5917e7781 +Revises: 96a9f3537996 +Create Date: 2018-07-30 13:51:29.576931 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.orm.session import Session + + +# revision identifiers, used by Alembic. +revision = '4ea5917e7781' +down_revision = '96a9f3537996' +branch_labels = None +depends_on = None + +from atst.models.role import Role +from atst.models.permissions import Permissions + + +def upgrade(): + session = Session(bind=op.get_bind()) + mission_owner_role = Role( + name='default', + description='', + permissions=[ + Permissions.REQUEST_JEDI_WORKSPACE, + ] + ) + session.add(mission_owner_role) + session.commit() + + +def downgrade(): + db = op.get_bind() + db.execute("DELETE FROM roles WHERE name = 'default'") + diff --git a/alembic/versions/96a9f3537996_add_roles_and_permissions.py b/alembic/versions/96a9f3537996_add_roles_and_permissions.py new file mode 100644 index 00000000..4380208a --- /dev/null +++ b/alembic/versions/96a9f3537996_add_roles_and_permissions.py @@ -0,0 +1,183 @@ +"""add_roles_and_permissions + +Revision ID: 96a9f3537996 +Revises: 4ede1e3e50d1 +Create Date: 2018-07-30 13:48:31.325234 + +""" +import os +import sys +from alembic import op +import sqlalchemy as sa + +from sqlalchemy.orm.session import Session + +from atst.models.role import Role +from atst.models.permissions import Permissions + +# revision identifiers, used by Alembic. +revision = '96a9f3537996' +down_revision = '4ede1e3e50d1' +branch_labels = None +depends_on = None + + +def upgrade(): + session = Session(bind=op.get_bind()) + roles = [ + Role( + name='ccpo', + description='', + permissions=[ + Permissions.VIEW_ORIGINAL_JEDI_REQEUST, + Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST, + Permissions.MODIFY_ATAT_ROLE_PERMISSIONS, + Permissions.CREATE_CSP_ROLE, + Permissions.DELETE_CSP_ROLE, + Permissions.DEACTIVE_CSP_ROLE, + Permissions.MODIFY_CSP_ROLE_PERMISSIONS, + + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.DEACTIVATE_WORKSPACE, + Permissions.VIEW_ATAT_PERMISSIONS, + Permissions.TRANSFER_OWNERSHIP_OF_WORKSPACE, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + + Permissions.ADD_TAG_TO_WORKSPACE, + Permissions.REMOVE_TAG_FROM_WORKSPACE + ] + ), + Role( + name='owner', + description='', + permissions=[ + Permissions.REQUEST_JEDI_WORKSPACE, + Permissions.VIEW_ORIGINAL_JEDI_REQEUST, + + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.DEACTIVATE_WORKSPACE, + Permissions.VIEW_ATAT_PERMISSIONS, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='admin', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='developer', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION + ] + ), + Role( + name='billing_auditor', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='security_auditor', + description='', + permissions=[ + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.VIEW_ATAT_PERMISSIONS, + + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + ] + ), + ] + + session.add_all(roles) + session.commit() + + +def downgrade(): + db = op.get_bind() + db.execute(""" + DELETE FROM roles + WHERE name IN ( + 'ccpo', + 'owner', + 'admin', + 'developer', + 'billing_auditor', + 'security_auditor' + ); + """) From 232b8192f54798485ba648b09aa6dd88eb59dd37 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 14:04:05 -0400 Subject: [PATCH 054/173] update handlers to user Users repo for managing authorization --- atst/app.py | 11 +++-------- atst/domain/roles.py | 13 +++++++------ atst/domain/users.py | 18 ++++++++---------- atst/handler.py | 21 +++++++-------------- atst/handlers/dev.py | 12 +++++------- atst/handlers/login_redirect.py | 4 ++-- atst/handlers/request.py | 1 + atst/handlers/request_submit.py | 1 + atst/handlers/workspaces.py | 4 ++-- tests/conftest.py | 1 - 10 files changed, 36 insertions(+), 50 deletions(-) diff --git a/atst/app.py b/atst/app.py index a488b4bf..830b7169 100644 --- a/atst/app.py +++ b/atst/app.py @@ -35,7 +35,7 @@ def make_app(config, deps, **kwargs): { "sessions": deps["sessions"], "authnid_client": deps["authnid_client"], - "authz_client": deps["authz_client"], + "db_session": deps["db_session"], }, name="login_redirect", ), @@ -50,7 +50,7 @@ def make_app(config, deps, **kwargs): url( r"/workspaces", Workspaces, - {"page": "workspaces", "authz_client": deps["authz_client"]}, + {"page": "workspaces", "db_session": deps["db_session"]}, name="workspaces", ), url( @@ -137,7 +137,7 @@ def make_app(config, deps, **kwargs): { "action": "login", "sessions": deps["sessions"], - "authz_client": deps["authz_client"], + "db_session": deps["db_session"], }, name="dev-login", ) @@ -168,11 +168,6 @@ def make_deps(config): return { "db_session": make_db(config), - "authz_client": ApiClient( - config["default"]["AUTHZ_BASE_URL"], - api_version="v1", - validate_cert=validate_cert, - ), "authnid_client": ApiClient( config["default"]["AUTHNID_BASE_URL"], api_version="v1", diff --git a/atst/domain/roles.py b/atst/domain/roles.py index 1b5f66c0..87a36961 100644 --- a/atst/domain/roles.py +++ b/atst/domain/roles.py @@ -5,15 +5,16 @@ from .exceptions import NotFoundError class Roles(object): - @classmethod - def get(cls, role_name): + def __init__(self, db_session): + self.db_session = db_session + + def get(self, role_name): try: - role = Role.query.filter_by(name=role_name).one() + role = self.db_session.query(Role).filter_by(name=role_name).one() except NoResultFound: raise NotFoundError("role") return role - @classmethod - def get_all(cls): - return Role.query.all() + def get_all(self): + return self.db_session.query(Role).all() diff --git a/atst/domain/users.py b/atst/domain/users.py index ace13eb5..94e99056 100644 --- a/atst/domain/users.py +++ b/atst/domain/users.py @@ -11,18 +11,19 @@ class Users(object): def __init__(self, db_session): self.db_session = db_session + self.roles_repo = Roles(db_session) def get(self, user_id): try: - user = User.query.filter_by(id=user_id).one() + user = self.db_session.query(User).filter_by(id=user_id).one() except NoResultFound: raise NotFoundError("user") return user def create(self, user_id, atat_role_name): - atat_role = Roles.get(atat_role_name) + atat_role = self.roles_repo.get(atat_role_name) try: user = User(id=user_id, atat_role=atat_role) @@ -34,22 +35,19 @@ class Users(object): return user def get_or_create(self, user_id, *args, **kwargs): - created = False - try: - user = Users.get(user_id) + user = self.get(user_id) except NotFoundError: - user = Users.create(user_id, *args, **kwargs) + user = self.create(user_id, *args, **kwargs) self.db_session.add(user) self.db_session.commit() - created = True - return user, created + return user def update(self, user_id, atat_role_name): - user = Users.get(user_id) - atat_role = Roles.get(atat_role_name) + user = self.get(user_id) + atat_role = self.roles_repo.get(atat_role_name) user.atat_role = atat_role self.db_session.add(user) diff --git a/atst/handler.py b/atst/handler.py index 3766aa95..bcbcf879 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -1,6 +1,7 @@ import tornado.web from atst.assets import environment from atst.sessions import SessionNotFoundError +from atst.domain.users import Users helpers = {"assets": environment} @@ -15,26 +16,18 @@ class BaseHandler(tornado.web.RequestHandler): @tornado.gen.coroutine def login(self, user): - user_permissions = yield self._get_user_permissions(user["id"]) - user["atat_permissions"] = user_permissions["atat_permissions"] - user["atat_role"] = user_permissions["atat_role"] + db_user = yield self._get_user_permissions(user["id"]) + user["atat_permissions"] = db_user.atat_permissions + user["atat_role"] = db_user.atat_role.name session_id = self.sessions.start_session(user) self.set_secure_cookie("atat", session_id) return self.redirect("/home") @tornado.gen.coroutine def _get_user_permissions(self, user_id): - response = yield self.authz_client.get( - "/users/{}".format(user_id), raise_error=False - ) - if response.code == 404: - response = yield self.authz_client.post( - "/users", json={"id": user_id, "atat_role": "developer"} - ) - return response.json - - else: - return response.json + user_repo = Users(self.db_session) + user = user_repo.get_or_create(user_id, atat_role_name="developer") + return user def get_current_user(self): cookie = self.get_secure_cookie("atat") diff --git a/atst/handlers/dev.py b/atst/handlers/dev.py index 878aca11..4394936b 100644 --- a/atst/handlers/dev.py +++ b/atst/handlers/dev.py @@ -1,6 +1,7 @@ import tornado.gen from atst.handler import BaseHandler +from atst.domain.users import Users _DEV_USERS = { "sam": { @@ -9,7 +10,6 @@ _DEV_USERS = { "last_name": "Seeceepio", "atat_role": "ccpo" }, - "amanda": { "id": "cce17030-4109-4719-b958-ed109dbb87c8", "first_name": "Amanda", @@ -44,10 +44,11 @@ _DEV_USERS = { class Dev(BaseHandler): - def initialize(self, action, sessions, authz_client): + def initialize(self, action, sessions, db_session): + self.db_session = db_session self.action = action self.sessions = sessions - self.authz_client = authz_client + self.users_repo = Users(db_session) @tornado.gen.coroutine def get(self): @@ -58,7 +59,4 @@ class Dev(BaseHandler): @tornado.gen.coroutine def _set_user_permissions(self, user_id, role): - response = yield self.authz_client.post( - "/users", json={"id": user_id, "atat_role": role} - ) - return response.json + return self.users_repo.get_or_create(user_id, atat_role_name=role) diff --git a/atst/handlers/login_redirect.py b/atst/handlers/login_redirect.py index 59fb8751..7746e934 100644 --- a/atst/handlers/login_redirect.py +++ b/atst/handlers/login_redirect.py @@ -3,10 +3,10 @@ from atst.handler import BaseHandler class LoginRedirect(BaseHandler): - def initialize(self, authnid_client, sessions, authz_client): + def initialize(self, authnid_client, sessions, db_session): + self.db_session = db_session self.authnid_client = authnid_client self.sessions = sessions - self.authz_client = authz_client @tornado.gen.coroutine def get(self): diff --git a/atst/handlers/request.py b/atst/handlers/request.py index 1373280a..6918526e 100644 --- a/atst/handlers/request.py +++ b/atst/handlers/request.py @@ -22,6 +22,7 @@ def map_request(user, request): class Request(BaseHandler): def initialize(self, page, db_session): self.page = page + self.db_session = db_session self.requests = Requests(db_session) @tornado.web.authenticated diff --git a/atst/handlers/request_submit.py b/atst/handlers/request_submit.py index ff27803b..116e996a 100644 --- a/atst/handlers/request_submit.py +++ b/atst/handlers/request_submit.py @@ -6,6 +6,7 @@ from atst.domain.requests import Requests class RequestsSubmit(BaseHandler): def initialize(self, db_session): + self.db_session = db_session self.requests_repo = Requests(db_session) @tornado.web.authenticated diff --git a/atst/handlers/workspaces.py b/atst/handlers/workspaces.py index c7e06451..b6fa1dbe 100644 --- a/atst/handlers/workspaces.py +++ b/atst/handlers/workspaces.py @@ -12,9 +12,9 @@ mock_workspaces = [ class Workspaces(BaseHandler): - def initialize(self, page, authz_client): + def initialize(self, page, db_session): self.page = page - self.authz_client = authz_client + self.db_session = db_session @tornado.gen.coroutine @tornado.web.authenticated diff --git a/tests/conftest.py b/tests/conftest.py index a0ed8550..555e1f79 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,6 @@ from atst.sessions import DictSessions @pytest.fixture def app(db): TEST_DEPS = { - "authz_client": MockAuthzClient("authz"), "authnid_client": MockApiClient("authnid"), "fundz_client": MockFundzClient("fundz"), "sessions": DictSessions(), From be29c5804fe9420957384160d1c74146fa69b146 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 14:19:38 -0400 Subject: [PATCH 055/173] add WorkspaceUser tests from authz --- atst/domain/workspace_users.py | 18 ++++++++---- tests/domain/test_workspace_users.py | 43 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/domain/test_workspace_users.py diff --git a/atst/domain/workspace_users.py b/atst/domain/workspace_users.py index 9ff139cd..857be057 100644 --- a/atst/domain/workspace_users.py +++ b/atst/domain/workspace_users.py @@ -1,17 +1,23 @@ from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.dialects.postgresql import insert -from atst.models import User, WorkspaceRole, Role +from atst.models.workspace_role import WorkspaceRole +from atst.models.workspace_user import WorkspaceUser +from atst.models.user import User +from .roles import Roles +from .users import Users from .exceptions import NotFoundError class WorkspaceUsers(object): def __init__(self, db_session): self.db_session = db_session + self.roles_repo = Roles(db_session) + self.users_repo = Users(db_session) def get(self, workspace_id, user_id): try: - user = User.query.filter_by(id=user_id).one() + user = self.users_repo.get(user_id) except NoResultFound: raise NotFoundError("user") @@ -31,18 +37,18 @@ class WorkspaceUsers(object): for user_dict in workspace_user_dicts: try: - user = User.query.filter_by(id=user_dict["id"]).one() + user = self.users_repo.get(user_dict["id"]) except NoResultFound: - default_role = Role.query.filter_by(name="developer").one_or_none() + default_role = self.roles_repo.get("developer") user = User(id=user_dict["id"], atat_role=default_role) try: - role = Role.query.filter_by(name=user_dict["workspace_role"]).one() + role = self.roles_repo.get(user_dict["workspace_role"]) except NoResultFound: raise NotFoundError("role") try: - existing_workspace_role = WorkspaceRole.query.filter( + existing_workspace_role = self.db_session.query(WorkspaceRole).filter( WorkspaceRole.user == user, WorkspaceRole.workspace_id == workspace_id, ).one() diff --git a/tests/domain/test_workspace_users.py b/tests/domain/test_workspace_users.py new file mode 100644 index 00000000..e86662f3 --- /dev/null +++ b/tests/domain/test_workspace_users.py @@ -0,0 +1,43 @@ +import pytest +from uuid import uuid4 + +from atst.domain.workspace_users import WorkspaceUsers +from atst.domain.users import Users + + +@pytest.fixture() +def users_repo(db): + return Users(db) + +@pytest.fixture() +def workspace_users_repo(db): + return WorkspaceUsers(db) + +def test_can_create_new_workspace_user(users_repo, workspace_users_repo): + workspace_id = uuid4() + user = users_repo.create(uuid4(), "developer") + + workspace_user_dicts = [ + {"id": user.id, "workspace_role": "owner"} + ] + + workspace_users = workspace_users_repo.add_many(workspace_id, workspace_user_dicts) + + assert workspace_users[0].user.id == user.id + assert workspace_users[0].user.atat_role.name == "developer" + assert workspace_users[0].workspace_role.role.name == "owner" + + +def test_can_update_existing_workspace_user(users_repo, workspace_users_repo): + workspace_id = uuid4() + user = users_repo.create(uuid4(), "developer") + + workspace_users_repo.add_many(workspace_id, [ + {"id": user.id, "workspace_role": "owner"} + ]) + workspace_users = workspace_users_repo.add_many(workspace_id, [ + {"id": user.id, "workspace_role": "developer"} + ]) + + assert workspace_users[0].user.id == user.id + assert workspace_users[0].workspace_role.role.name == "developer" From c4039de861486fe2ffd5451ceb74f9fc806604ff Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 30 Jul 2018 15:31:14 -0400 Subject: [PATCH 056/173] Add domain tests for all of authz --- tests/domain/test_roles.py | 23 ++++++++++++ tests/domain/test_users.py | 72 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tests/domain/test_roles.py create mode 100644 tests/domain/test_users.py diff --git a/tests/domain/test_roles.py b/tests/domain/test_roles.py new file mode 100644 index 00000000..1280292f --- /dev/null +++ b/tests/domain/test_roles.py @@ -0,0 +1,23 @@ +import pytest +from atst.domain.roles import Roles +from atst.domain.exceptions import NotFoundError + + +@pytest.fixture() +def roles_repo(db): + return Roles(db) + + +def test_get_all_roles(roles_repo): + roles = roles_repo.get_all() + assert roles + + +def test_get_existing_role(roles_repo): + role = roles_repo.get("developer") + assert role.name == "developer" + + +def test_get_nonexistent_role(roles_repo): + with pytest.raises(NotFoundError): + roles_repo.get("nonexistent") diff --git a/tests/domain/test_users.py b/tests/domain/test_users.py new file mode 100644 index 00000000..921463f8 --- /dev/null +++ b/tests/domain/test_users.py @@ -0,0 +1,72 @@ +import pytest +from uuid import uuid4, UUID + +from atst.domain.users import Users +from atst.domain.exceptions import NotFoundError, AlreadyExistsError + +@pytest.fixture() +def users_repo(db) -> Users: + return Users(db) + + +@pytest.fixture(scope="function") +def user_id(): + return uuid4() + + +def test_create_user(users_repo, user_id): + user = users_repo.create(user_id, "developer") + assert user.id == user_id + + +def test_create_user_with_nonexistent_role(users_repo, user_id): + with pytest.raises(NotFoundError): + users_repo.create(user_id, "nonexistent") + + +def test_create_already_existing_user(users_repo, user_id): + users_repo.create(user_id, "developer") + with pytest.raises(AlreadyExistsError): + users_repo.create(user_id, "developer") + + +def test_get_or_create_nonexistent_user(users_repo, user_id): + user = users_repo.get_or_create(user_id, atat_role_name="developer") + assert user.id == user_id + + +def test_get_or_create_existing_user(users_repo, user_id): + users_repo.get_or_create(user_id, atat_role_name="developer") + user = users_repo.get_or_create(user_id, atat_role_name="developer") + assert user + + +def test_get_user(users_repo, user_id): + users_repo.create(user_id, "developer") + user = users_repo.get(user_id) + assert user.id == user_id + + +def test_get_nonexistent_user(users_repo, user_id): + users_repo.create(user_id, "developer") + with pytest.raises(NotFoundError): + users_repo.get(uuid4()) + + +def test_update_user(users_repo, user_id): + users_repo.create(user_id, "developer") + updated_user = users_repo.update(user_id, "ccpo") + + assert updated_user.atat_role.name == "ccpo" + + +def test_update_nonexistent_user(users_repo, user_id): + users_repo.create(user_id, "developer") + with pytest.raises(NotFoundError): + users_repo.update(uuid4(), "ccpo") + + +def test_update_existing_user_with_nonexistent_role(users_repo, user_id): + users_repo.create(user_id, "developer") + with pytest.raises(NotFoundError): + users_repo.update(user_id, "nonexistent") From 8fdf3ec20f60e502760931b6312d739e374f574c Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 30 Jul 2018 15:33:19 -0400 Subject: [PATCH 057/173] Formatting --- atst/domain/users.py | 2 -- atst/domain/workspace_users.py | 14 +++++++++----- atst/domain/workspaces.py | 2 -- tests/domain/test_users.py | 1 + tests/domain/test_workspace_users.py | 18 +++++++++--------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/atst/domain/users.py b/atst/domain/users.py index 94e99056..76385228 100644 --- a/atst/domain/users.py +++ b/atst/domain/users.py @@ -8,12 +8,10 @@ from .exceptions import NotFoundError, AlreadyExistsError class Users(object): - def __init__(self, db_session): self.db_session = db_session self.roles_repo = Roles(db_session) - def get(self, user_id): try: user = self.db_session.query(User).filter_by(id=user_id).one() diff --git a/atst/domain/workspace_users.py b/atst/domain/workspace_users.py index 857be057..e4d93c19 100644 --- a/atst/domain/workspace_users.py +++ b/atst/domain/workspace_users.py @@ -8,8 +8,8 @@ from .roles import Roles from .users import Users from .exceptions import NotFoundError -class WorkspaceUsers(object): +class WorkspaceUsers(object): def __init__(self, db_session): self.db_session = db_session self.roles_repo = Roles(db_session) @@ -48,10 +48,14 @@ class WorkspaceUsers(object): raise NotFoundError("role") try: - existing_workspace_role = self.db_session.query(WorkspaceRole).filter( - WorkspaceRole.user == user, - WorkspaceRole.workspace_id == workspace_id, - ).one() + existing_workspace_role = ( + self.db_session.query(WorkspaceRole) + .filter( + WorkspaceRole.user == user, + WorkspaceRole.workspace_id == workspace_id, + ) + .one() + ) new_workspace_role = existing_workspace_role new_workspace_role.role = role except NoResultFound: diff --git a/atst/domain/workspaces.py b/atst/domain/workspaces.py index b4cc85b8..6ec0b856 100644 --- a/atst/domain/workspaces.py +++ b/atst/domain/workspaces.py @@ -1,5 +1,4 @@ class Projects(object): - def __init__(self): pass @@ -47,7 +46,6 @@ class Projects(object): class Members(object): - def __init__(self): pass diff --git a/tests/domain/test_users.py b/tests/domain/test_users.py index 921463f8..a76a9ae8 100644 --- a/tests/domain/test_users.py +++ b/tests/domain/test_users.py @@ -4,6 +4,7 @@ from uuid import uuid4, UUID from atst.domain.users import Users from atst.domain.exceptions import NotFoundError, AlreadyExistsError + @pytest.fixture() def users_repo(db) -> Users: return Users(db) diff --git a/tests/domain/test_workspace_users.py b/tests/domain/test_workspace_users.py index e86662f3..f76bdf3e 100644 --- a/tests/domain/test_workspace_users.py +++ b/tests/domain/test_workspace_users.py @@ -9,17 +9,17 @@ from atst.domain.users import Users def users_repo(db): return Users(db) + @pytest.fixture() def workspace_users_repo(db): return WorkspaceUsers(db) + def test_can_create_new_workspace_user(users_repo, workspace_users_repo): workspace_id = uuid4() user = users_repo.create(uuid4(), "developer") - workspace_user_dicts = [ - {"id": user.id, "workspace_role": "owner"} - ] + workspace_user_dicts = [{"id": user.id, "workspace_role": "owner"}] workspace_users = workspace_users_repo.add_many(workspace_id, workspace_user_dicts) @@ -32,12 +32,12 @@ def test_can_update_existing_workspace_user(users_repo, workspace_users_repo): workspace_id = uuid4() user = users_repo.create(uuid4(), "developer") - workspace_users_repo.add_many(workspace_id, [ - {"id": user.id, "workspace_role": "owner"} - ]) - workspace_users = workspace_users_repo.add_many(workspace_id, [ - {"id": user.id, "workspace_role": "developer"} - ]) + workspace_users_repo.add_many( + workspace_id, [{"id": user.id, "workspace_role": "owner"}] + ) + workspace_users = workspace_users_repo.add_many( + workspace_id, [{"id": user.id, "workspace_role": "developer"}] + ) assert workspace_users[0].user.id == user.id assert workspace_users[0].workspace_role.role.name == "developer" From d23975ad028db2f192fe5c85c5c8fc8d82d8d0fb Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 30 Jul 2018 15:37:31 -0400 Subject: [PATCH 058/173] Fix linting errors --- atst/domain/workspace_users.py | 1 - tests/conftest.py | 2 +- tests/domain/test_users.py | 2 +- tests/factories.py | 2 +- tests/mocks.py | 49 ---------------------------------- 5 files changed, 3 insertions(+), 53 deletions(-) diff --git a/atst/domain/workspace_users.py b/atst/domain/workspace_users.py index e4d93c19..ef51b78d 100644 --- a/atst/domain/workspace_users.py +++ b/atst/domain/workspace_users.py @@ -1,5 +1,4 @@ from sqlalchemy.orm.exc import NoResultFound -from sqlalchemy.dialects.postgresql import insert from atst.models.workspace_role import WorkspaceRole from atst.models.workspace_user import WorkspaceUser diff --git a/tests/conftest.py b/tests/conftest.py index 555e1f79..04510f1b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import sessionmaker, scoped_session from atst.app import make_app, make_deps, make_config from atst.database import make_db -from tests.mocks import MockApiClient, MockFundzClient, MockAuthzClient +from tests.mocks import MockApiClient, MockFundzClient from atst.sessions import DictSessions diff --git a/tests/domain/test_users.py b/tests/domain/test_users.py index a76a9ae8..f136e3bd 100644 --- a/tests/domain/test_users.py +++ b/tests/domain/test_users.py @@ -1,5 +1,5 @@ import pytest -from uuid import uuid4, UUID +from uuid import uuid4 from atst.domain.users import Users from atst.domain.exceptions import NotFoundError, AlreadyExistsError diff --git a/tests/factories.py b/tests/factories.py index b07b36fa..1c870308 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -1,7 +1,7 @@ import factory from uuid import uuid4 -from atst.models import Request, RequestStatusEvent +from atst.models import Request class RequestFactory(factory.Factory): diff --git a/tests/mocks.py b/tests/mocks.py index 96c22e4a..3a277b0f 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -70,52 +70,3 @@ class MockFundzClient(MockApiClient): return self._get_response("GET", path, 200) else: return self._get_response("GET", path, 404) - - -class MockAuthzClient(MockApiClient): - _json = { - "atat_permissions": [ - "view_original_jedi_request", - "review_and_approve_jedi_workspace_request", - "modify_atat_role_permissions", - "create_csp_role", - "delete_csp_role", - "deactivate_csp_role", - "modify_csp_role_permissions", - "view_usage_report", - "view_usage_dollars", - "add_and_assign_csp_roles", - "remove_csp_roles", - "request_new_csp_role", - "assign_and_unassign_atat_role", - "view_assigned_atat_role_configurations", - "view_assigned_csp_role_configurations", - "deactivate_workspace", - "view_atat_permissions", - "transfer_ownership_of_workspace", - "add_application_in_workspace", - "delete_application_in_workspace", - "deactivate_application_in_workspace", - "view_application_in_workspace", - "rename_application_in_workspace", - "add_environment_in_application", - "delete_environment_in_application", - "deactivate_environment_in_application", - "view_environment_in_application", - "rename_environment_in_application", - "add_tag_to_workspace", - "remove_tag_from_workspace", - ], - "atat_role": "ccpo", - "id": "164497f6-c1ea-4f42-a5ef-101da278c012", - "username": None, - "workspace_roles": [], - } - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return self._get_response("POST", path, 200, json=self._json) - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return self._get_response("POST", path, 200, json=self._json) From 4742957f6d153404e7897c23d105da241f044069 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 30 Jul 2018 15:40:37 -0400 Subject: [PATCH 059/173] Remove unnecessary type hint --- tests/domain/test_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/domain/test_users.py b/tests/domain/test_users.py index f136e3bd..9a2245b9 100644 --- a/tests/domain/test_users.py +++ b/tests/domain/test_users.py @@ -6,7 +6,7 @@ from atst.domain.exceptions import NotFoundError, AlreadyExistsError @pytest.fixture() -def users_repo(db) -> Users: +def users_repo(db): return Users(db) From e14aac24c40ce6df50d7bfd4593d0efd0c53421f Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 10:50:22 -0400 Subject: [PATCH 060/173] remove authz url reference in config --- config/base.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/config/base.ini b/config/base.ini index 78d56c36..285eb11f 100644 --- a/config/base.ini +++ b/config/base.ini @@ -2,7 +2,6 @@ PORT=8000 ENVIRONMENT = dev DEBUG = true -AUTHZ_BASE_URL = http://localhost:8002 AUTHNID_BASE_URL= https://localhost:8001 FUNDZ_BASE_URL= http://localhost:8004 COOKIE_SECRET = some-secret-please-replace From c02a95d00a686daf26aff0e1000a4d43df24381b Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 14:46:37 -0400 Subject: [PATCH 061/173] import fundz models --- .../versions/55ba973d08b9_add_fundz_models.py | 38 +++++++++++++++++++ atst/models/__init__.py | 2 + atst/models/pe_number.py | 13 +++++++ atst/models/task_order.py | 9 +++++ 4 files changed, 62 insertions(+) create mode 100644 alembic/versions/55ba973d08b9_add_fundz_models.py create mode 100644 atst/models/pe_number.py create mode 100644 atst/models/task_order.py diff --git a/alembic/versions/55ba973d08b9_add_fundz_models.py b/alembic/versions/55ba973d08b9_add_fundz_models.py new file mode 100644 index 00000000..097532f4 --- /dev/null +++ b/alembic/versions/55ba973d08b9_add_fundz_models.py @@ -0,0 +1,38 @@ +"""add_fundz_models + +Revision ID: 55ba973d08b9 +Revises: 4ea5917e7781 +Create Date: 2018-07-30 14:43:34.099799 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '55ba973d08b9' +down_revision = '4ea5917e7781' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('pe_number', + sa.Column('number', sa.String(), nullable=False), + sa.Column('description', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('number') + ) + op.create_table('task_order', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('number', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('task_order') + op.drop_table('pe_number') + # ### end Alembic commands ### diff --git a/atst/models/__init__.py b/atst/models/__init__.py index fef82003..1d6daae1 100644 --- a/atst/models/__init__.py +++ b/atst/models/__init__.py @@ -8,3 +8,5 @@ from .permissions import Permissions from .role import Role from .user import User from .workspace_role import WorkspaceRole +from .pe_number import PENumber +from .task_order import TaskOrder diff --git a/atst/models/pe_number.py b/atst/models/pe_number.py new file mode 100644 index 00000000..61a0755e --- /dev/null +++ b/atst/models/pe_number.py @@ -0,0 +1,13 @@ +from sqlalchemy import String, Column + +from atst.models import Base + +class PENumber(Base): + __tablename__ = "pe_number" + + number = Column(String, primary_key=True) + description = Column(String) + + def __repr__(self): + return "".format( + self.number, self.description) diff --git a/atst/models/task_order.py b/atst/models/task_order.py new file mode 100644 index 00000000..7a7879a7 --- /dev/null +++ b/atst/models/task_order.py @@ -0,0 +1,9 @@ +from sqlalchemy import Column, Integer, String + +from atst.models import Base + +class TaskOrder(Base): + __tablename__ = "task_order" + + id = Column(Integer, primary_key=True) + number = Column(String) From 2e13c4772b5cf73c6c0b51cec707bc0ff81645a4 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 15:50:33 -0400 Subject: [PATCH 062/173] domain repos for PE numbers and task orders --- atst/domain/pe_numbers.py | 15 ++++++++++++++ atst/domain/task_orders.py | 18 +++++++++++++++++ tests/domain/test_pe_numbers.py | 34 ++++++++++++++++++++++++++++++++ tests/domain/test_task_orders.py | 34 ++++++++++++++++++++++++++++++++ tests/factories.py | 12 ++++++++++- 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 atst/domain/pe_numbers.py create mode 100644 atst/domain/task_orders.py create mode 100644 tests/domain/test_pe_numbers.py create mode 100644 tests/domain/test_task_orders.py diff --git a/atst/domain/pe_numbers.py b/atst/domain/pe_numbers.py new file mode 100644 index 00000000..07d79585 --- /dev/null +++ b/atst/domain/pe_numbers.py @@ -0,0 +1,15 @@ +from atst.models.pe_number import PENumber +from .exceptions import NotFoundError + + +class PENumbers(object): + + def __init__(self, db_session): + self.db_session = db_session + + def get(self, number): + pe_number = self.db_session.query(PENumber).get(number) + if not pe_number: + raise NotFoundError("pe_number") + + return pe_number diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py new file mode 100644 index 00000000..cbc4cc4e --- /dev/null +++ b/atst/domain/task_orders.py @@ -0,0 +1,18 @@ +from sqlalchemy.orm.exc import NoResultFound + +from atst.models.task_order import TaskOrder +from .exceptions import NotFoundError + + +class TaskOrders(object): + + def __init__(self, db_session): + self.db_session = db_session + + def get(self, order_number): + try: + task_order = self.db_session.query(TaskOrder).filter_by(number=order_number).one() + except NoResultFound: + raise NotFoundError("task_order") + + return task_order diff --git a/tests/domain/test_pe_numbers.py b/tests/domain/test_pe_numbers.py new file mode 100644 index 00000000..ba9025be --- /dev/null +++ b/tests/domain/test_pe_numbers.py @@ -0,0 +1,34 @@ +import pytest + +from atst.domain.exceptions import NotFoundError +from atst.domain.pe_numbers import PENumbers + +from tests.factories import PENumberFactory + + +@pytest.fixture() +def pe_numbers(db): + return PENumbers(db) + +@pytest.fixture(scope="function") +def new_pe_number(db): + def make_pe_number(**kwargs): + pen = PENumberFactory.create(**kwargs) + db.add(pen) + db.commit() + + return pen + + return make_pe_number + + +def test_can_get_pe_number(pe_numbers, new_pe_number): + new_pen = new_pe_number(number="0101969F", description="Combat Support - Offensive") + pen = pe_numbers.get(new_pen.number) + + assert pen.number == new_pen.number + + +def test_nonexistent_pe_number_raises(pe_numbers): + with pytest.raises(NotFoundError): + pe_numbers.get("some fake number") diff --git a/tests/domain/test_task_orders.py b/tests/domain/test_task_orders.py new file mode 100644 index 00000000..9b7c0882 --- /dev/null +++ b/tests/domain/test_task_orders.py @@ -0,0 +1,34 @@ +import pytest + +from atst.domain.exceptions import NotFoundError +from atst.domain.task_orders import TaskOrders + +from tests.factories import TaskOrderFactory + + +@pytest.fixture() +def task_orders(db): + return TaskOrders(db) + +@pytest.fixture(scope="function") +def new_task_order(db): + def make_task_order(**kwargs): + to = TaskOrderFactory.create(**kwargs) + db.add(to) + db.commit() + + return to + + return make_task_order + + +def test_can_get_task_order(task_orders, new_task_order): + new_to = new_task_order(number="0101969F") + to = task_orders.get(new_to.number) + + assert to.id == to.id + + +def test_nonexistent_task_order_raises(task_orders): + with pytest.raises(NotFoundError): + task_orders.get("some fake number") diff --git a/tests/factories.py b/tests/factories.py index 1c870308..582ce461 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -1,7 +1,9 @@ import factory from uuid import uuid4 -from atst.models import Request +from atst.models import Request, RequestStatusEvent +from atst.models.pe_number import PENumber +from atst.models.task_order import TaskOrder class RequestFactory(factory.Factory): @@ -9,3 +11,11 @@ class RequestFactory(factory.Factory): model = Request id = factory.Sequence(lambda x: uuid4()) + +class PENumberFactory(factory.Factory): + class Meta: + model = PENumber + +class TaskOrderFactory(factory.Factory): + class Meta: + model = TaskOrder From c2d5c52577ef2f23a7edf4e2c7af31376e2c1c19 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 30 Jul 2018 16:25:15 -0400 Subject: [PATCH 063/173] remove fundz_client in favor of pe numbers repo --- atst/app.py | 7 ------- atst/forms/financial.py | 16 ++++++++-------- atst/handlers/request_financial_verification.py | 7 ++++--- atst/handlers/request_new.py | 15 ++++++++------- tests/conftest.py | 1 - tests/handlers/test_financial_verification.py | 10 +++++++--- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/atst/app.py b/atst/app.py index 830b7169..a94a93ec 100644 --- a/atst/app.py +++ b/atst/app.py @@ -65,7 +65,6 @@ def make_app(config, deps, **kwargs): { "page": "requests_new", "db_session": deps["db_session"], - "fundz_client": deps["fundz_client"], }, name="request_new", ), @@ -75,7 +74,6 @@ def make_app(config, deps, **kwargs): { "page": "requests_new", "db_session": deps["db_session"], - "fundz_client": deps["fundz_client"], }, name="request_form_new", ), @@ -85,7 +83,6 @@ def make_app(config, deps, **kwargs): { "page": "requests_new", "db_session": deps["db_session"], - "fundz_client": deps["fundz_client"], }, name="request_form_update", ), @@ -108,7 +105,6 @@ def make_app(config, deps, **kwargs): { "page": "financial_verification", "db_session": deps["db_session"], - "fundz_client": deps["fundz_client"], }, name="financial_verification", ), @@ -173,9 +169,6 @@ def make_deps(config): api_version="v1", validate_cert=validate_cert, ), - "fundz_client": ApiClient( - config["default"]["FUNDZ_BASE_URL"], validate_cert=validate_cert - ), "sessions": RedisSessions( redis_client, config["default"]["SESSION_TTL_SECONDS"] ), diff --git a/atst/forms/financial.py b/atst/forms/financial.py index 9c2a669c..52b4ef28 100644 --- a/atst/forms/financial.py +++ b/atst/forms/financial.py @@ -6,6 +6,8 @@ from wtforms.fields import StringField, SelectField from wtforms.form import Form from wtforms.validators import Required, Email +from atst.domain.exceptions import NotFoundError + from .fields import NewlineListField from .forms import ValidatedForm @@ -35,12 +37,10 @@ def suggest_pe_id(pe_id): @tornado.gen.coroutine -def validate_pe_id(field, existing_request, fundz_client): - response = yield fundz_client.get( - "/pe-number/{}".format(field.data), - raise_error=False, - ) - if not response.ok: +def validate_pe_id(field, existing_request, pe_numbers_repo): + try: + pe_number = pe_numbers_repo.get(field.data) + except NotFoundError: suggestion = suggest_pe_id(field.data) error_str = ( "We couldn't find that PE number. {}" @@ -56,10 +56,10 @@ def validate_pe_id(field, existing_request, fundz_client): class FinancialForm(ValidatedForm): @tornado.gen.coroutine - def perform_extra_validation(self, existing_request, fundz_client): + def perform_extra_validation(self, existing_request, pe_numbers_repo): valid = True if not existing_request or existing_request.get('pe_id') != self.pe_id.data: - valid = yield validate_pe_id(self.pe_id, existing_request, fundz_client) + valid = yield validate_pe_id(self.pe_id, existing_request, pe_numbers_repo) raise Return(valid) task_order_id = StringField( diff --git a/atst/handlers/request_financial_verification.py b/atst/handlers/request_financial_verification.py index a063692c..e93f999c 100644 --- a/atst/handlers/request_financial_verification.py +++ b/atst/handlers/request_financial_verification.py @@ -3,13 +3,14 @@ import tornado from atst.handler import BaseHandler from atst.forms.financial import FinancialForm from atst.domain.requests import Requests +from atst.domain.pe_numbers import PENumbers class RequestFinancialVerification(BaseHandler): - def initialize(self, page, db_session, fundz_client): + def initialize(self, page, db_session): self.page = page self.requests_repo = Requests(db_session) - self.fundz_client = fundz_client + self.pe_numbers_repo = PENumbers(db_session) def get_existing_request(self, request_id): return self.requests_repo.get(request_id) @@ -48,7 +49,7 @@ class RequestFinancialVerification(BaseHandler): yield self.update_request(request_id, form.data) valid = yield form.perform_extra_validation( existing_request.body.get('financial_verification'), - self.fundz_client + self.pe_numbers_repo ) if valid: self.redirect( diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 67c24585..1d33daa0 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -7,13 +7,14 @@ from atst.forms.org import OrgForm from atst.forms.poc import POCForm from atst.forms.review import ReviewForm from atst.domain.requests import Requests +from atst.domain.pe_numbers import PENumbers class RequestNew(BaseHandler): - def initialize(self, page, db_session, fundz_client): + def initialize(self, page, db_session): self.page = page self.requests_repo = Requests(db_session) - self.fundz_client = fundz_client + self.pe_numbers_repo = PENumbers(db_session) def get_existing_request(self, request_id): if request_id is None: @@ -31,7 +32,7 @@ class RequestNew(BaseHandler): existing_request = self.get_existing_request(request_id) jedi_flow = JEDIRequestFlow( self.requests_repo, - self.fundz_client, + self.pe_numbers_repo, screen, post_data=post_data, request_id=request_id, @@ -81,7 +82,7 @@ class RequestNew(BaseHandler): request = self.requests_repo.get(request_id) jedi_flow = JEDIRequestFlow( - self.requests_repo, self.fundz_client, screen, request, request_id=request_id + self.requests_repo, self.pe_numbers_repo, screen, request, request_id=request_id ) self.render( @@ -101,7 +102,7 @@ class JEDIRequestFlow(object): def __init__( self, requests_repo, - fundz_client, + pe_numbers_repo, current_step, request=None, post_data=None, @@ -110,7 +111,7 @@ class JEDIRequestFlow(object): existing_request=None, ): self.requests_repo = requests_repo - self.fundz_client = fundz_client + self.pe_numbers_repo = pe_numbers_repo self.current_step = current_step self.request = request @@ -144,7 +145,7 @@ class JEDIRequestFlow(object): valid = yield self.form.perform_extra_validation( existing_request_data, - self.fundz_client, + self.pe_numbers_repo, ) return valid diff --git a/tests/conftest.py b/tests/conftest.py index 04510f1b..92da1bce 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,6 @@ from atst.sessions import DictSessions def app(db): TEST_DEPS = { "authnid_client": MockApiClient("authnid"), - "fundz_client": MockFundzClient("fundz"), "sessions": DictSessions(), "db_session": db } diff --git a/tests/handlers/test_financial_verification.py b/tests/handlers/test_financial_verification.py index 57b8851d..d84f76bd 100644 --- a/tests/handlers/test_financial_verification.py +++ b/tests/handlers/test_financial_verification.py @@ -2,7 +2,8 @@ import re import pytest import tornado import urllib -from tests.mocks import MOCK_REQUEST, MOCK_USER, MOCK_VALID_PE_ID +from tests.mocks import MOCK_REQUEST, MOCK_USER +from tests.factories import PENumberFactory class TestPENumberInForm: @@ -73,11 +74,14 @@ class TestPENumberInForm: assert response.headers.get("Location") == "/requests/financial_verification_submitted" @pytest.mark.gen_test - def test_submit_request_form_with_new_valid_pe_id(self, monkeypatch, http_client, base_url): + def test_submit_request_form_with_new_valid_pe_id(self, db, monkeypatch, http_client, base_url): self._set_monkeypatches(monkeypatch) + pe = PENumberFactory.create(number="8675309U", description="sample PE number") + db.add(pe) + db.commit() data = dict(self.required_data) - data['pe_id'] = MOCK_VALID_PE_ID + data['pe_id'] = pe.number response = yield self.submit_data(http_client, base_url, data) From 5f1db135c3189c130aea42cdb0baeeb519b8e6b4 Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 09:21:33 -0400 Subject: [PATCH 064/173] add script for ingesting PE numbers and necessary script config for database --- config/base.ini | 1 + script/ingest_pe_numbers.py | 40 +++++++++++++++++++++++++++++++++++++ script/setup | 3 +++ script/update | 3 +++ 4 files changed, 47 insertions(+) create mode 100644 script/ingest_pe_numbers.py diff --git a/config/base.ini b/config/base.ini index 285eb11f..8b3a6881 100644 --- a/config/base.ini +++ b/config/base.ini @@ -7,6 +7,7 @@ FUNDZ_BASE_URL= http://localhost:8004 COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret CAC_URL = https://localhost:8001 +PE_NUMBER_CSV_URL = http://c95e1ebb198426ee57b8-174bb05a294821bedbf46b6384fe9b1f.r31.cf5.rackcdn.com/penumbers.csv REDIS_URI = redis://localhost:6379 SESSION_TTL_SECONDS = 600 PGAPPNAME = atst diff --git a/script/ingest_pe_numbers.py b/script/ingest_pe_numbers.py new file mode 100644 index 00000000..1df5b132 --- /dev/null +++ b/script/ingest_pe_numbers.py @@ -0,0 +1,40 @@ +from urllib.request import urlopen +import csv + +from sqlalchemy.dialects.postgresql import insert + +# Add root project dir to the python path +import os +import sys +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.append(parent_dir) + +from atst.app import make_deps, make_config +from atst.models import PENumber + + +def get_pe_numbers(url): + response = urlopen(url) + t = response.read().decode("utf-8") + return list(csv.reader(t.split("\r\n"))) + + +def insert_pe_numbers(db, list_of_pe_numbers): + stmt = insert(PENumber).values(list_of_pe_numbers) + do_update = stmt.on_conflict_do_update( + index_elements=["number"], + set_=dict(description=stmt.excluded.description) + ) + db.execute(do_update) + db.commit() + + +if __name__ == "__main__": + config = make_config() + deps = make_deps(config) + db = deps["db_session"] + url = config["default"]['PE_NUMBER_CSV_URL'] + print("Fetching PE numbers from {}".format(url)) + pe_numbers = get_pe_numbers(url) + print("Inserting {} PE numbers".format(len(pe_numbers))) + insert_pe_numbers(db, pe_numbers) diff --git a/script/setup b/script/setup index 5cd11461..bf83b19a 100755 --- a/script/setup +++ b/script/setup @@ -16,3 +16,6 @@ RESET_DB="true" # Run the shared setup script source ./script/include/run_setup + +# Fetch and import the PE numbers +run_command "python script/ingest_pe_numbers.py" diff --git a/script/update b/script/update index 1baef9a8..46d5d549 100755 --- a/script/update +++ b/script/update @@ -9,3 +9,6 @@ MIGRATE_DB="true" # Run the shared update script source ./script/include/run_update + +# Fetch and import/update the PE numbers +run_command "python script/ingest_pe_numbers.py" From 080d48dc388688fd24d576675ec778152c187fa5 Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 11:19:29 -0400 Subject: [PATCH 065/173] fix pe number test to add non-existent pe number --- tests/domain/test_pe_numbers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/domain/test_pe_numbers.py b/tests/domain/test_pe_numbers.py index ba9025be..332ae688 100644 --- a/tests/domain/test_pe_numbers.py +++ b/tests/domain/test_pe_numbers.py @@ -23,7 +23,7 @@ def new_pe_number(db): def test_can_get_pe_number(pe_numbers, new_pe_number): - new_pen = new_pe_number(number="0101969F", description="Combat Support - Offensive") + new_pen = new_pe_number(number="0701367F", description="Combat Support - Offensive") pen = pe_numbers.get(new_pen.number) assert pen.number == new_pen.number From a37711b47aa7726ad7a3454ad6c117b9cc38d345 Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 11:21:48 -0400 Subject: [PATCH 066/173] remove reference to fundz in config and api mocks --- config/base.ini | 1 - tests/conftest.py | 2 +- tests/mocks.py | 9 --------- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/config/base.ini b/config/base.ini index 8b3a6881..e8be9197 100644 --- a/config/base.ini +++ b/config/base.ini @@ -3,7 +3,6 @@ PORT=8000 ENVIRONMENT = dev DEBUG = true AUTHNID_BASE_URL= https://localhost:8001 -FUNDZ_BASE_URL= http://localhost:8004 COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret CAC_URL = https://localhost:8001 diff --git a/tests/conftest.py b/tests/conftest.py index 92da1bce..0921f2bf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import sessionmaker, scoped_session from atst.app import make_app, make_deps, make_config from atst.database import make_db -from tests.mocks import MockApiClient, MockFundzClient +from tests.mocks import MockApiClient from atst.sessions import DictSessions diff --git a/tests/mocks.py b/tests/mocks.py index 3a277b0f..c8903099 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -61,12 +61,3 @@ class MockApiClient(ApiClient): MOCK_VALID_PE_ID = "8675309U" - -class MockFundzClient(MockApiClient): - - @tornado.gen.coroutine - def get(self, path, **kwargs): - if path.endswith(MOCK_VALID_PE_ID): - return self._get_response("GET", path, 200) - else: - return self._get_response("GET", path, 404) From 5f27ae2015b097233006c415493dfc2c3409928e Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 31 Jul 2018 11:43:09 -0400 Subject: [PATCH 067/173] move logic for creating many PE Numbers to the domain repo --- atst/domain/pe_numbers.py | 11 +++++++++++ script/ingest_pe_numbers.py | 23 +++++++---------------- tests/domain/test_pe_numbers.py | 7 +++++++ 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/atst/domain/pe_numbers.py b/atst/domain/pe_numbers.py index 07d79585..a80e10ef 100644 --- a/atst/domain/pe_numbers.py +++ b/atst/domain/pe_numbers.py @@ -1,3 +1,5 @@ +from sqlalchemy.dialects.postgresql import insert + from atst.models.pe_number import PENumber from .exceptions import NotFoundError @@ -13,3 +15,12 @@ class PENumbers(object): raise NotFoundError("pe_number") return pe_number + + def create_many(self, list_of_pe_numbers): + stmt = insert(PENumber).values(list_of_pe_numbers) + do_update = stmt.on_conflict_do_update( + index_elements=["number"], + set_=dict(description=stmt.excluded.description) + ) + self.db_session.execute(do_update) + self.db_session.commit() diff --git a/script/ingest_pe_numbers.py b/script/ingest_pe_numbers.py index 1df5b132..e3bbecb0 100644 --- a/script/ingest_pe_numbers.py +++ b/script/ingest_pe_numbers.py @@ -1,8 +1,6 @@ from urllib.request import urlopen import csv -from sqlalchemy.dialects.postgresql import insert - # Add root project dir to the python path import os import sys @@ -10,7 +8,7 @@ parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(parent_dir) from atst.app import make_deps, make_config -from atst.models import PENumber +from atst.domain.pe_numbers import PENumbers def get_pe_numbers(url): @@ -18,23 +16,16 @@ def get_pe_numbers(url): t = response.read().decode("utf-8") return list(csv.reader(t.split("\r\n"))) - -def insert_pe_numbers(db, list_of_pe_numbers): - stmt = insert(PENumber).values(list_of_pe_numbers) - do_update = stmt.on_conflict_do_update( - index_elements=["number"], - set_=dict(description=stmt.excluded.description) - ) - db.execute(do_update) - db.commit() - +def make_pe_number_repo(config): + deps = make_deps(config) + db = deps["db_session"] + return PENumbers(db) if __name__ == "__main__": config = make_config() - deps = make_deps(config) - db = deps["db_session"] url = config["default"]['PE_NUMBER_CSV_URL'] print("Fetching PE numbers from {}".format(url)) pe_numbers = get_pe_numbers(url) print("Inserting {} PE numbers".format(len(pe_numbers))) - insert_pe_numbers(db, pe_numbers) + pe_numbers_repo = make_pe_number_repo(config) + pe_numbers_repo.create_many(pe_numbers) diff --git a/tests/domain/test_pe_numbers.py b/tests/domain/test_pe_numbers.py index 332ae688..028aa712 100644 --- a/tests/domain/test_pe_numbers.py +++ b/tests/domain/test_pe_numbers.py @@ -32,3 +32,10 @@ def test_can_get_pe_number(pe_numbers, new_pe_number): def test_nonexistent_pe_number_raises(pe_numbers): with pytest.raises(NotFoundError): pe_numbers.get("some fake number") + +def test_create_many(pe_numbers): + pen_list = [['123456', 'Land Speeder'], ['7891011', 'Lightsaber']] + pe_numbers.create_many(pen_list) + + assert pe_numbers.get(pen_list[0][0]) + assert pe_numbers.get(pen_list[1][0]) From 63e3db7d511af8b5b12192780ac4e3f112a399a7 Mon Sep 17 00:00:00 2001 From: dandds Date: Wed, 1 Aug 2018 09:06:48 -0400 Subject: [PATCH 068/173] fix missing import from rebase --- tests/handlers/test_request_new.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/handlers/test_request_new.py b/tests/handlers/test_request_new.py index 3373c867..8409fc13 100644 --- a/tests/handlers/test_request_new.py +++ b/tests/handlers/test_request_new.py @@ -3,6 +3,7 @@ import pytest import tornado import urllib from tests.mocks import MOCK_USER +from tests.factories import RequestFactory ERROR_CLASS = "alert--error" MOCK_REQUEST = RequestFactory.create( From 1af0f5e579a460232919ff18875f07df5cd4fa01 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 1 Aug 2018 10:51:14 -0400 Subject: [PATCH 069/173] Flask setup --- Pipfile | 13 +- Pipfile.lock | 196 ++++++++++++++++++++------- app.py | 12 +- atst/app.py | 290 ++++++++++++++++++++-------------------- atst/assets.py | 11 +- atst/database.py | 9 +- atst/handler.py | 3 +- atst/routes/__init__.py | 7 + 8 files changed, 318 insertions(+), 223 deletions(-) create mode 100644 atst/routes/__init__.py diff --git a/Pipfile b/Pipfile index 81cadd0d..4110ccbf 100644 --- a/Pipfile +++ b/Pipfile @@ -4,20 +4,23 @@ verify_ssl = true name = "pypi" [packages] -tornado = "==5.0.2" -webassets = "==0.12.1" -Unipath = "==1.1" +tornado = "*" +webassets = "*" +Unipath = "*" wtforms-tornado = "*" pendulum = "*" redis = "*" sqlalchemy = "*" alembic = "*" "psycopg2-binary" = "*" +flask = "*" +flask-sqlalchemy = "*" +flask-assets = "*" [dev-packages] bandit = "*" -pytest = "==3.6.0" -pytest-tornado = "==0.5.0" +pytest = "*" +pytest-tornado = "*" ipython = "*" ipdb = "*" pylint = "*" diff --git a/Pipfile.lock b/Pipfile.lock index d87dfa97..d6e5cf64 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7cd87f2c2c42bc776a6aa6f72fcbb8b30d4e703e50b6480ce1c8ace6ae6dd0a4" + "sha256": "2ee6dd90ff3784e7b1781c680d690ac59118b4e3d72e8da3adf9e93d6e512bc7" }, "pipfile-spec": 6, "requires": { @@ -24,6 +24,49 @@ "index": "pypi", "version": "==1.0.0" }, + "click": { + "hashes": [ + "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", + "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" + ], + "version": "==6.7" + }, + "flask": { + "hashes": [ + "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", + "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" + ], + "index": "pypi", + "version": "==1.0.2" + }, + "flask-assets": { + "hashes": [ + "sha256:6031527b89fb3509d1581d932affa5a79dd348cfffb58d0aef99a43461d47847" + ], + "index": "pypi", + "version": "==0.12" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b", + "sha256:5971b9852b5888655f11db634e87725a9031e170f37c0ce7851cf83497f56e53" + ], + "index": "pypi", + "version": "==2.3.2" + }, + "itsdangerous": { + "hashes": [ + "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + ], + "version": "==0.24" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, "mako": { "hashes": [ "sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae" @@ -38,19 +81,22 @@ }, "pendulum": { "hashes": [ - "sha256:0643d45824e6789b88187728337dfa6075a0233f6976c2abefba00d064156309", - "sha256:3cc271195d8054bec06f54ff7d56ea6c2e2b5ad5dd6b532d787b34d2cabe6a65", - "sha256:544e44d8a92954e5ef4db4fa8b662d3282f2ac7b7c2cbf4227dc193ba78b9e1e", - "sha256:846478ab5f7480b3d850a09e44fe03830d448633c84f0b1066615ff6c34293aa", - "sha256:8bb523f759daeecfc0649369f198cbeb27a6608347354f4f847d21d579003db6", - "sha256:a449142063100f1b3c1119453c7569667c9ba79897305a1c50ca83a8c790f1e4", - "sha256:b7ff156b3d7cccbdeeb63465578d9a4e6f57d463f6ff6d4474254208d08f8353", - "sha256:d8822a592bbc16576c44ec4625bff9187ed9b649d47714e4905a55adc5b25339", - "sha256:dd45c7b349faab69714df9835cdf8bf8bce50bf6fc471419d3b23ba33e1915a5", - "sha256:fac088b637b5db5a047a0e89194d8c3c9e9e9ce1665089240003bb7c05b92536" + "sha256:0ec5371949e147753661e1e98721273170638034dfceb578f29d69d93d3d474b", + "sha256:10ccdc8c6d004ba97883dd0f57503963ddf6cb83e849a16c4675ba18da657564", + "sha256:37bb54bcbb9d7fccd725f3fda69702e51ab3de9971b4c1c986505fbb3bc58bed", + "sha256:51803352e40778f914ff7af3494788b404260b415d9a9d607a8cf73e5e120994", + "sha256:5de295ca85761d9adf4020e6f3bed6eb933846ccf23b74e04b071f6d677f11a4", + "sha256:73f850265adcf0986fcc0af83ae9c8c5a7ca3c4a2525184110478a8bfd1a77b3", + "sha256:8fe289356322f6b0f4510082b4c412a1496a64054a37ae86b24411868a1901c6", + "sha256:c0401482dfa9fbd7005f2dfbf54ec61fd2c8130df37651ac2a3722d1f049ae4e", + "sha256:c358ee65ddb99c2b1bf301458e43ed09ff6d40465bcc9928265246912fad4d0f", + "sha256:d07962450e808556b3e6209a5830e2bbf8c7747129580c3b5b09e641f72617ab", + "sha256:dc05e6186c9c3b9969326aded9cba7a796744918581b25457f5148a5e3475d55", + "sha256:ee9466eea403e8e308c284d3055e285b97905a5ffb1566df0ef200b4f39c0f15", + "sha256:f7fa6220251a636112721e8158b9dd59018d818ec121047900934d80864eca62" ], "index": "pypi", - "version": "==2.0.2" + "version": "==2.0.3" }, "psycopg2-binary": { "hashes": [ @@ -106,7 +152,7 @@ "sha256:1d936da41ee06216d89fdc7ead1ee9a5da2811a8787515a976b646e110c3f622", "sha256:e4ef42e82b0b493c5849eed98b5ab49d6767caf982127e9a33167f1153b36cc5" ], - "markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.3.*' and python_version >= '2.7'", + "markers": "python_version != '3.0.*' and python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.3.*'", "version": "==2018.5" }, "redis": { @@ -133,14 +179,16 @@ }, "tornado": { "hashes": [ - "sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7", - "sha256:408d129e9d13d3c55aa73f8084aa97d5f90ed84132e38d6932e63a67d5bec563", - "sha256:88ce0282cce70df9045e515f578c78f1ebc35dcabe1d70f800c3583ebda7f5f5", - "sha256:ba9fbb249ac5390bff8a1d6aa4b844fd400701069bda7d2e380dfe2217895101", - "sha256:c050089173c2e9272244bccfb6a8615fb9e53b79420a5551acfa76094ecc3111" + "sha256:1c0816fc32b7d31b98781bd8ebc7a9726d7dce67407dc353a2e66e697e138448", + "sha256:4f66a2172cb947387193ca4c2c3e19131f1c70fa8be470ddbbd9317fd0801582", + "sha256:5327ba1a6c694e0149e7d9126426b3704b1d9d520852a3e4aa9fc8fe989e4046", + "sha256:6a7e8657618268bb007646b9eae7661d0b57f13efc94faa33cd2588eae5912c9", + "sha256:a9b14804783a1d77c0bd6c66f7a9b1196cbddfbdf8bceb64683c5ae60bd1ec6f", + "sha256:c58757e37c4a3172949c99099d4d5106e4d7b63aa0617f9bb24bfbff712c7866", + "sha256:d8984742ce86c0855cccecd5c6f54a9f7532c983947cff06f3a0e2115b47f85c" ], "index": "pypi", - "version": "==5.0.2" + "version": "==5.1" }, "unipath": { "hashes": [ @@ -157,6 +205,13 @@ "index": "pypi", "version": "==0.12.1" }, + "werkzeug": { + "hashes": [ + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + ], + "version": "==0.14.1" + }, "wtforms": { "hashes": [ "sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61", @@ -197,10 +252,10 @@ }, "astroid": { "hashes": [ - "sha256:0a0c484279a5f08c9bcedd6fa9b42e378866a7dcc695206b92d59dc9f2d9760d", - "sha256:218e36cf8d98a42f16214e8670819ce307fa707d1dcf7f9af84c7aede1febc7f" + "sha256:a48b57ede295c3188ef5c84273bc2a8eadc46e4cbb001eae0d49fb5d1fabbb19", + "sha256:d066cdeec5faeb51a4be5010da612680653d844b57afd86a5c8315f2f801b4cc" ], - "version": "==2.0.1" + "version": "==2.0.2" }, "atomicwrites": { "hashes": [ @@ -279,7 +334,7 @@ "sha256:0e9a1227a3a0f3297a485715e72ee6eb77081b17b629367042b586e38c03c867", "sha256:b4840807a94a3bad0217d6ed3f9b65a1cc6e1db1c99e1184673056ae2c0a4c4d" ], - "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*'", + "markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.0.*'", "version": "==0.8.17" }, "gitdb2": { @@ -305,11 +360,11 @@ }, "ipython": { "hashes": [ - "sha256:a0c96853549b246991046f32d19db7140f5b1a644cc31f0dc1edc86713b7676f", - "sha256:eca537aa61592aca2fef4adea12af8e42f5c335004dfa80c78caf80e8b525e5c" + "sha256:007dcd929c14631f83daff35df0147ea51d1af420da303fd078343878bd5fb62", + "sha256:b0f2ef9eada4a68ef63ee10b6dde4f35c840035c50fd24265f8052c98947d5a4" ], "index": "pypi", - "version": "==6.4.0" + "version": "==6.5.0" }, "ipython-genutils": { "hashes": [ @@ -324,7 +379,7 @@ "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" ], - "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", + "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*'", "version": "==4.3.4" }, "jedi": { @@ -377,11 +432,11 @@ }, "more-itertools": { "hashes": [ - "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", - "sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", - "sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0" + "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", + "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", + "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" ], - "version": "==4.2.0" + "version": "==4.3.0" }, "parso": { "hashes": [ @@ -398,10 +453,10 @@ }, "pbr": { "hashes": [ - "sha256:754e766b4f4bad3aa68cfd532456298da1aa39375da8748392dbae90860d5f18", - "sha256:c6bddbad814f23c7faaf88d8a186e9965243cc6206a23361b73023648e645794" + "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45", + "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa" ], - "version": "==4.1.1" + "version": "==4.2.0" }, "pexpect": { "hashes": [ @@ -420,12 +475,11 @@ }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", + "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], - "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", - "version": "==0.6.0" + "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*'", + "version": "==0.7.1" }, "prompt-toolkit": { "hashes": [ @@ -447,7 +501,7 @@ "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], - "markers": "python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*'", + "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*'", "version": "==1.5.4" }, "pygments": { @@ -459,19 +513,19 @@ }, "pylint": { "hashes": [ - "sha256:2c90a24bee8fae22ac98061c896e61f45c5b73c2e0511a4bf53f99ba56e90434", - "sha256:454532779425098969b8f54ab0f056000b883909f69d05905ea114df886e3251" + "sha256:0edfec21270725c5aa8e8d8d06ef5666f766e0e748ed2f1ab23624727303b935", + "sha256:4cadcaa4f1fb19123d4baa758d9fbe6286c5b3aa513af6ea42a2d51d405db205" ], "index": "pypi", - "version": "==2.0.1" + "version": "==2.1.0" }, "pytest": { "hashes": [ - "sha256:39555d023af3200d004d09e51b4dd9fdd828baa863cded3fd6ba2f29f757ae2d", - "sha256:c76e93f3145a44812955e8d46cdd302d8a45fbfc7bf22be24fe231f9d8d8853a" + "sha256:8214ab8446104a1d0c17fbd218ec6aac743236c6ffbe23abc038e40213c60b88", + "sha256:e2b2c6e1560b8f9dc8dd600b0923183fbd68ba3d9bdecde04467be6dd296a384" ], "index": "pypi", - "version": "==3.6.0" + "version": "==3.7.0" }, "pytest-tornado": { "hashes": [ @@ -547,14 +601,16 @@ }, "tornado": { "hashes": [ - "sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7", - "sha256:408d129e9d13d3c55aa73f8084aa97d5f90ed84132e38d6932e63a67d5bec563", - "sha256:88ce0282cce70df9045e515f578c78f1ebc35dcabe1d70f800c3583ebda7f5f5", - "sha256:ba9fbb249ac5390bff8a1d6aa4b844fd400701069bda7d2e380dfe2217895101", - "sha256:c050089173c2e9272244bccfb6a8615fb9e53b79420a5551acfa76094ecc3111" + "sha256:1c0816fc32b7d31b98781bd8ebc7a9726d7dce67407dc353a2e66e697e138448", + "sha256:4f66a2172cb947387193ca4c2c3e19131f1c70fa8be470ddbbd9317fd0801582", + "sha256:5327ba1a6c694e0149e7d9126426b3704b1d9d520852a3e4aa9fc8fe989e4046", + "sha256:6a7e8657618268bb007646b9eae7661d0b57f13efc94faa33cd2588eae5912c9", + "sha256:a9b14804783a1d77c0bd6c66f7a9b1196cbddfbdf8bceb64683c5ae60bd1ec6f", + "sha256:c58757e37c4a3172949c99099d4d5106e4d7b63aa0617f9bb24bfbff712c7866", + "sha256:d8984742ce86c0855cccecd5c6f54a9f7532c983947cff06f3a0e2115b47f85c" ], "index": "pypi", - "version": "==5.0.2" + "version": "==5.1" }, "traitlets": { "hashes": [ @@ -563,6 +619,42 @@ ], "version": "==4.3.2" }, + "typed-ast": { + "hashes": [ + "sha256:0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", + "sha256:10703d3cec8dcd9eef5a630a04056bbc898abc19bac5691612acba7d1325b66d", + "sha256:1f6c4bd0bdc0f14246fd41262df7dfc018d65bb05f6e16390b7ea26ca454a291", + "sha256:25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", + "sha256:29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", + "sha256:2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", + "sha256:3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", + "sha256:519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", + "sha256:57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa", + "sha256:668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", + "sha256:68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", + "sha256:6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", + "sha256:79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", + "sha256:8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", + "sha256:898f818399cafcdb93cbbe15fc83a33d05f18e29fb498ddc09b0214cdfc7cd51", + "sha256:94b091dc0f19291adcb279a108f5d38de2430411068b219f41b343c03b28fb1f", + "sha256:a26863198902cda15ab4503991e8cf1ca874219e0118cbf07c126bce7c4db129", + "sha256:a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", + "sha256:bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", + "sha256:c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", + "sha256:c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", + "sha256:edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", + "sha256:f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6" + ], + "version": "==1.1.0" + }, + "typing": { + "hashes": [ + "sha256:3a887b021a77b292e151afb75323dea88a7bc1b3dfa92176cff8e44c8b68bddf", + "sha256:b2c689d54e1144bbcfd191b0832980a21c2dbcf7b5ff7a66248a60c90e951eb8", + "sha256:d400a9344254803a2368533e4533a4200d21eb7b6b729c173bc38201a74db3f2" + ], + "version": "==3.6.4" + }, "watchdog": { "hashes": [ "sha256:7e65882adb7746039b6f3876ee174952f8eaaa34491ba34333ddf1fe35de4162" diff --git a/app.py b/app.py index b6d66f53..6d786f34 100755 --- a/app.py +++ b/app.py @@ -1,15 +1,11 @@ #!/usr/bin/env python -import tornado.ioloop - -from atst.app import make_app, make_deps, make_config +from atst.app import make_app, make_config config = make_config() -deps = make_deps(config) -app = make_app(config, deps) +app = make_app(config) if __name__ == "__main__": - port = int(config["default"]["PORT"]) - app.listen(port) + port = int(config["PORT"]) + app.run(port=port) print("Listening on http://localhost:%i" % port) - tornado.ioloop.IOLoop.current().start() diff --git a/atst/app.py b/atst/app.py index a94a93ec..5128117f 100644 --- a/atst/app.py +++ b/atst/app.py @@ -1,160 +1,166 @@ import os from configparser import ConfigParser -import tornado.web -from tornado.web import url from redis import StrictRedis +from flask import Flask +from unipath import Path -from atst.handlers.main import Main -from atst.handlers.root import Root -from atst.handlers.login_redirect import LoginRedirect -from atst.handlers.workspaces import Workspaces -from atst.handlers.workspace import Workspace -from atst.handlers.workspace_members import WorkspaceMembers -from atst.handlers.request import Request -from atst.handlers.request_financial_verification import RequestFinancialVerification -from atst.handlers.request_new import RequestNew -from atst.handlers.request_submit import RequestsSubmit -from atst.handlers.dev import Dev -from atst.home import home from atst.api_client import ApiClient from atst.sessions import RedisSessions -from atst import ui_modules -from atst import ui_methods -from atst.database import make_db +from atst.database import db +from atst.assets import assets +from atst.routes import bp ENV = os.getenv("TORNADO_ENV", "dev") -def make_app(config, deps, **kwargs): +def make_app(config): - routes = [ - url(r"/", Root, {"page": "root"}, name="root"), - url( - r"/login-redirect", - LoginRedirect, - { - "sessions": deps["sessions"], - "authnid_client": deps["authnid_client"], - "db_session": deps["db_session"], - }, - name="login_redirect", - ), - url(r"/home", Main, {"page": "home"}, name="home"), - url(r"/styleguide", Main, {"page": "styleguide"}, name="styleguide"), - url( - r"/workspaces/blank", - Main, - {"page": "workspaces_blank"}, - name="workspaces_blank", - ), - url( - r"/workspaces", - Workspaces, - {"page": "workspaces", "db_session": deps["db_session"]}, - name="workspaces", - ), - url( - r"/requests", - Request, - {"page": "requests", "db_session": deps["db_session"]}, - name="requests", - ), - url( - r"/requests/new", - RequestNew, - { - "page": "requests_new", - "db_session": deps["db_session"], - }, - name="request_new", - ), - url( - r"/requests/new/([0-9])", - RequestNew, - { - "page": "requests_new", - "db_session": deps["db_session"], - }, - name="request_form_new", - ), - url( - r"/requests/new/([0-9])/(\S+)", - RequestNew, - { - "page": "requests_new", - "db_session": deps["db_session"], - }, - name="request_form_update", - ), - url( - r"/requests/submit/(\S+)", - RequestsSubmit, - {"db_session": deps["db_session"]}, - name="requests_submit", - ), - # Dummy request/approval screen - url( - r"/request/approval", - Main, - {"page": "request_approval"}, - name="request_approval", - ), - url( - r"/requests/verify/(\S+)", - RequestFinancialVerification, - { - "page": "financial_verification", - "db_session": deps["db_session"], - }, - name="financial_verification", - ), - url( - r"/requests/financial_verification_submitted", - Main, - {"page": "requests/financial_verification_submitted"}, - name="financial_verification_submitted", - ), - url(r"/users", Main, {"page": "users"}, name="users"), - url(r"/reports", Main, {"page": "reports"}, name="reports"), - url(r"/calculator", Main, {"page": "calculator"}, name="calculator"), - url( - r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members" - ), - url(r"/workspaces/(\S+)/projects", Workspace, {}, name="workspace_projects"), - url(r"/workspaces/123456/projects/789/edit", Main, {"page": "project_edit"}, name="project_edit"), - url(r"/workspaces/123456/members/789/edit", Main, {"page": "member_edit"}, name="member_edit"), - ] + parent_dir = Path().parent - if not ENV == "production": - routes += [ - url( - r"/login-dev", - Dev, - { - "action": "login", - "sessions": deps["sessions"], - "db_session": deps["db_session"], - }, - name="dev-login", - ) - ] - - app = tornado.web.Application( - routes, - login_url="/", - template_path=home.child("templates"), - static_path=home.child("static"), - cookie_secret=config["default"]["COOKIE_SECRET"], - debug=config["default"].getboolean("DEBUG"), - ui_modules=ui_modules, - ui_methods=ui_methods, - **kwargs + app = Flask( + __name__, + template_folder=parent_dir.child("templates").absolute(), + static_folder=parent_dir.child("static").absolute() ) - app.config = config - app.sessions = deps["sessions"] + app.config.update(config) + + db.init_app(app) + assets.init_app(app) + + app.register_blueprint(bp) + return app +# def make_app(config, deps, **kwargs): +# routes = [ +# url(r"/", Root, {"page": "root"}, name="root"), +# url( +# r"/login-redirect", +# LoginRedirect, +# { +# "sessions": deps["sessions"], +# "authnid_client": deps["authnid_client"], +# "db_session": deps["db_session"], +# }, +# name="login_redirect", +# ), +# url(r"/home", Main, {"page": "home"}, name="home"), +# url(r"/styleguide", Main, {"page": "styleguide"}, name="styleguide"), +# url( +# r"/workspaces/blank", +# Main, +# {"page": "workspaces_blank"}, +# name="workspaces_blank", +# ), +# url( +# r"/workspaces", +# Workspaces, +# {"page": "workspaces", "db_session": deps["db_session"]}, +# name="workspaces", +# ), +# url( +# r"/requests", +# Request, +# {"page": "requests", "db_session": deps["db_session"]}, +# name="requests", +# ), +# url( +# r"/requests/new", +# RequestNew, +# { +# "page": "requests_new", +# "db_session": deps["db_session"], +# }, +# name="request_new", +# ), +# url( +# r"/requests/new/([0-9])", +# RequestNew, +# { +# "page": "requests_new", +# "db_session": deps["db_session"], +# }, +# name="request_form_new", +# ), +# url( +# r"/requests/new/([0-9])/(\S+)", +# RequestNew, +# { +# "page": "requests_new", +# "db_session": deps["db_session"], +# }, +# name="request_form_update", +# ), +# url( +# r"/requests/submit/(\S+)", +# RequestsSubmit, +# {"db_session": deps["db_session"]}, +# name="requests_submit", +# ), +# # Dummy request/approval screen +# url( +# r"/request/approval", +# Main, +# {"page": "request_approval"}, +# name="request_approval", +# ), +# url( +# r"/requests/verify/(\S+)", +# RequestFinancialVerification, +# { +# "page": "financial_verification", +# "db_session": deps["db_session"], +# }, +# name="financial_verification", +# ), +# url( +# r"/requests/financial_verification_submitted", +# Main, +# {"page": "requests/financial_verification_submitted"}, +# name="financial_verification_submitted", +# ), +# url(r"/users", Main, {"page": "users"}, name="users"), +# url(r"/reports", Main, {"page": "reports"}, name="reports"), +# url(r"/calculator", Main, {"page": "calculator"}, name="calculator"), +# url( +# r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members" +# ), +# url(r"/workspaces/(\S+)/projects", Workspace, {}, name="workspace_projects"), +# url(r"/workspaces/123456/projects/789/edit", Main, {"page": "project_edit"}, name="project_edit"), +# url(r"/workspaces/123456/members/789/edit", Main, {"page": "member_edit"}, name="member_edit"), +# ] + +# if not ENV == "production": +# routes += [ +# url( +# r"/login-dev", +# Dev, +# { +# "action": "login", +# "sessions": deps["sessions"], +# "db_session": deps["db_session"], +# }, +# name="dev-login", +# ) +# ] + +# app = tornado.web.Application( +# routes, +# login_url="/", +# template_path=home.child("templates"), +# static_path=home.child("static"), +# cookie_secret=config["default"]["COOKIE_SECRET"], +# debug=config["default"].getboolean("DEBUG"), +# ui_modules=ui_modules, +# ui_methods=ui_methods, +# **kwargs +# ) +# app.config = config +# app.sessions = deps["sessions"] +# return app + + def make_deps(config): # we do not want to do SSL verify services in test and development validate_cert = ENV == "production" @@ -206,4 +212,4 @@ def make_config(): ) config.set("default", "DATABASE_URI", database_uri) - return config + return config["default"] diff --git a/atst/assets.py b/atst/assets.py index 7f723f75..bed898ac 100644 --- a/atst/assets.py +++ b/atst/assets.py @@ -1,16 +1,13 @@ -from webassets import Environment, Bundle +from flask_assets import Environment, Bundle from atst.home import home -environment = Environment( - directory=home.child("scss"), - url="/static" -) +assets = Environment() css = Bundle( - "atat.scss", + "../scss/atat.scss", filters="scss", output="../static/assets/out.%(version)s.css", depends=("**/*.scss"), ) -environment.register("css", css) +assets.register("css", css) diff --git a/atst/database.py b/atst/database.py index 6191f62e..f0b13d6f 100644 --- a/atst/database.py +++ b/atst/database.py @@ -1,8 +1,3 @@ -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker, scoped_session +from flask_sqlalchemy import SQLAlchemy - -def make_db(config): - engine = create_engine(config['default']['DATABASE_URI']) - session = scoped_session(sessionmaker(bind=engine)) - return session +db = SQLAlchemy() diff --git a/atst/handler.py b/atst/handler.py index bcbcf879..bc931a8d 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -1,9 +1,8 @@ import tornado.web -from atst.assets import environment from atst.sessions import SessionNotFoundError from atst.domain.users import Users -helpers = {"assets": environment} +helpers = {"assets": None} class BaseHandler(tornado.web.RequestHandler): diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py new file mode 100644 index 00000000..c6b03baf --- /dev/null +++ b/atst/routes/__init__.py @@ -0,0 +1,7 @@ +from flask import Blueprint, render_template + +bp = Blueprint("atst", __name__) + +@bp.route("/") +def home(): + return render_template("home.html") From 9d9c980eb02d4732cc73701d2509c46ef8b0ac80 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 1 Aug 2018 11:22:21 -0400 Subject: [PATCH 070/173] Convert ui methods into Flask globals --- atst/app.py | 31 +++++++++++++++++++++++++-- atst/routes/__init__.py | 2 +- templates/{base.html.to => base.html} | 22 +++++++++---------- templates/{home.html.to => home.html} | 4 ++-- 4 files changed, 42 insertions(+), 17 deletions(-) rename templates/{base.html.to => base.html} (60%) rename templates/{home.html.to => home.html} (68%) diff --git a/atst/app.py b/atst/app.py index 5128117f..f4cfe183 100644 --- a/atst/app.py +++ b/atst/app.py @@ -1,7 +1,8 @@ import os +import re from configparser import ConfigParser from redis import StrictRedis -from flask import Flask +from flask import Flask, request, g from unipath import Path from atst.api_client import ApiClient @@ -24,6 +25,8 @@ def make_app(config): ) app.config.update(config) + make_flask_callbacks(app) + db.init_app(app) assets.init_app(app) @@ -32,6 +35,21 @@ def make_app(config): return app +def make_flask_callbacks(app): + @app.before_request + def set_globals(): + g.navigationContext = 'workspace' if re.match('\/workspaces\/[A-Za-z0-9]*', request.url) else 'global' + g.dev = os.getenv("TORNADO_ENV", "dev") == "dev" + g.matchesPath = lambda href: re.match('^'+href, request.url) + g.modalOpen = request.args.get("modal", False) + + # TODO: Make me a macro + def modal(self, body): + return self.render_string( + "components/modal.html.to", + body=body) + + # def make_app(config, deps, **kwargs): # routes = [ # url(r"/", Root, {"page": "root"}, name="root"), @@ -180,6 +198,15 @@ def make_deps(config): ), } +def map_config(config): + return { + "ENV": config["default"]["ENVIRONMENT"], + "DEBUG": config["default"]["DEBUG"], + "PORT": int(config["default"]["PORT"]), + "SQLALCHEMY_DATABASE_URI": config["default"]["DATABASE_URI"], + "SQLALCHEMY_TRACK_MODIFICATIONS": False, + **config["default"] + } def make_config(): BASE_CONFIG_FILENAME = os.path.join(os.path.dirname(__file__), "../config/base.ini") @@ -212,4 +239,4 @@ def make_config(): ) config.set("default", "DATABASE_URI", database_uri) - return config["default"] + return map_config(config) diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py index c6b03baf..93fde8e2 100644 --- a/atst/routes/__init__.py +++ b/atst/routes/__init__.py @@ -1,4 +1,4 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, g bp = Blueprint("atst", __name__) diff --git a/templates/base.html.to b/templates/base.html similarity index 60% rename from templates/base.html.to rename to templates/base.html index 3f0d5995..58c804cb 100644 --- a/templates/base.html.to +++ b/templates/base.html @@ -1,21 +1,21 @@ {# TODO: set this context elsewhere #} {# set context='workspace' #} -{% set context=navigationContext() %} +{% set context=g.navigationContext %} - {% block title %}JEDI{% end %} - {% for url in assets['css'].urls() %} - - {% end %} + {% block title %}JEDI{% endblock %} + {% assets "css" %} + + {% endassets %} - + - {% block template_vars %}{% end %} + {% block template_vars %}{% endblock %} {% include 'navigation/topbar.html.to' %} @@ -23,18 +23,16 @@ {% include 'navigation/global_navigation.html.to' %}
    - {% block sidenav %}{% end %} + {% block sidenav %}{% endblock %} {% block content %} these are not the droids you are looking for - {% end %} + {% endblock %}
    {% include 'footer.html.to' %} - {% block modal %}{% end %} + {% block modal %}{% endblock %} - - diff --git a/templates/home.html.to b/templates/home.html similarity index 68% rename from templates/home.html.to rename to templates/home.html index eb789f28..0df70037 100644 --- a/templates/home.html.to +++ b/templates/home.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %} @@ -8,7 +8,7 @@ -{% end %} +{% endblock %} From 9c024e382a5cb95d59c222e6b53c544f9450efaa Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 1 Aug 2018 11:40:07 -0400 Subject: [PATCH 071/173] home.html is rendering - Converted Icon and SidenavItem into macros - Setting a mock user on g.current_user --- atst/app.py | 6 ++++ templates/components.html | 32 +++++++++++++++++++ .../navigation/global_navigation.html.to | 25 ++++++++------- templates/navigation/topbar.html.to | 9 +++--- 4 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 templates/components.html diff --git a/atst/app.py b/atst/app.py index f4cfe183..23ad724b 100644 --- a/atst/app.py +++ b/atst/app.py @@ -42,6 +42,12 @@ def make_flask_callbacks(app): g.dev = os.getenv("TORNADO_ENV", "dev") == "dev" g.matchesPath = lambda href: re.match('^'+href, request.url) g.modalOpen = request.args.get("modal", False) + g.current_user = { + "id": "cce17030-4109-4719-b958-ed109dbb87c8", + "first_name": "Amanda", + "last_name": "Adamson", + "atat_role": "default" + } # TODO: Make me a macro def modal(self, body): diff --git a/templates/components.html b/templates/components.html new file mode 100644 index 00000000..06d487ea --- /dev/null +++ b/templates/components.html @@ -0,0 +1,32 @@ +{% macro Icon(name, classes="") -%} + {% autoescape false %} + + {% endautoescape %} +{%- endmacro %} + +{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} +
  • + + {% if icon %} + {{ Icon(icon, classes="sidenav__link-icon") }} + {% endif %} + + {{label}} + + + {% if subnav and active %} + + {% endif %} +
  • +{%- endmacro %} diff --git a/templates/navigation/global_navigation.html.to b/templates/navigation/global_navigation.html.to index 60991d47..594bf574 100644 --- a/templates/navigation/global_navigation.html.to +++ b/templates/navigation/global_navigation.html.to @@ -1,24 +1,25 @@ +{% from "components.html" import SidenavItem %} diff --git a/templates/navigation/topbar.html.to b/templates/navigation/topbar.html.to index 9af26690..10fc0c6d 100644 --- a/templates/navigation/topbar.html.to +++ b/templates/navigation/topbar.html.to @@ -1,18 +1,19 @@ +{% from "components.html" import Icon %}
    From 494a91979718bd7acb9ba6f94def445950f8bb58 Mon Sep 17 00:00:00 2001 From: dandds Date: Wed, 1 Aug 2018 13:15:07 -0400 Subject: [PATCH 072/173] switch workspace routes and templates to Flask and Jinja --- atst/app.py | 2 ++ atst/routes/workspaces.py | 31 ++++++++++++++++++ ..._workspace.html.to => base_workspace.html} | 6 ++-- templates/components.html | 12 +++++++ .../navigation/workspace_navigation.html.to | 32 ++++++++++--------- ...members.html.to => workspace_members.html} | 16 ++++++---- ...ojects.html.to => workspace_projects.html} | 16 ++++++---- .../{workspaces.html.to => workspaces.html} | 6 ++-- 8 files changed, 86 insertions(+), 35 deletions(-) create mode 100644 atst/routes/workspaces.py rename templates/{base_workspace.html.to => base_workspace.html} (70%) rename templates/{workspace_members.html.to => workspace_members.html} (92%) rename templates/{workspace_projects.html.to => workspace_projects.html} (72%) rename templates/{workspaces.html.to => workspaces.html} (91%) diff --git a/atst/app.py b/atst/app.py index 23ad724b..087277fc 100644 --- a/atst/app.py +++ b/atst/app.py @@ -10,6 +10,7 @@ from atst.sessions import RedisSessions from atst.database import db from atst.assets import assets from atst.routes import bp +from atst.routes.workspaces import bp as workspace_routes ENV = os.getenv("TORNADO_ENV", "dev") @@ -31,6 +32,7 @@ def make_app(config): assets.init_app(app) app.register_blueprint(bp) + app.register_blueprint(workspace_routes) return app diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py new file mode 100644 index 00000000..1f3b47f2 --- /dev/null +++ b/atst/routes/workspaces.py @@ -0,0 +1,31 @@ +from flask import Blueprint, render_template + +from atst.domain.workspaces import Projects, Members +from atst.database import db + +bp = Blueprint("workspaces", __name__) + +mock_workspaces = [ + { + "name": "Unclassified IaaS and PaaS for Defense Digital Service (DDS)", + "id": "5966187a-eff9-44c3-aa15-4de7a65ac7ff", + "task_order": {"number": 123456}, + "user_count": 23, + } +] + +@bp.route("/workspaces") +def workspaces(): + return render_template("workspaces.html", page=5, workspaces=mock_workspaces) + +@bp.route("/workspaces//projects") +def workspace_projects(workspace_id): + projects_repo = Projects() + projects = projects_repo.get_many(workspace_id) + return render_template("workspace_projects.html", workspace_id=workspace_id, projects=projects) + +@bp.route("/workspaces//members") +def workspace_members(workspace_id): + members_repo = Members() + members = members_repo.get_many(workspace_id) + return render_template("workspace_members.html", workspace_id=workspace_id, members=members) diff --git a/templates/base_workspace.html.to b/templates/base_workspace.html similarity index 70% rename from templates/base_workspace.html.to rename to templates/base_workspace.html index 7803ace8..0ccad5ba 100644 --- a/templates/base_workspace.html.to +++ b/templates/base_workspace.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %} @@ -8,8 +8,8 @@
    - {% block workspace_content %}{% end %} + {% block workspace_content %}{% endblock %}
    -{% end %} +{% endblock %} diff --git a/templates/components.html b/templates/components.html index 06d487ea..0bc83991 100644 --- a/templates/components.html +++ b/templates/components.html @@ -30,3 +30,15 @@ {% endif %} {%- endmacro %} + +{% macro EmptyState(self, message, actionLabel, actionHref, icon=None) -%} +
    +

    {{ message }}

    + + {% if icon %} + {{ Icon(icon) }} + {% endif %} + + {{ actionLabel }} +
    +{%- endmacro %} diff --git a/templates/navigation/workspace_navigation.html.to b/templates/navigation/workspace_navigation.html.to index 65a9525b..d516c1b0 100644 --- a/templates/navigation/workspace_navigation.html.to +++ b/templates/navigation/workspace_navigation.html.to @@ -1,42 +1,44 @@ +{% from "components.html" import SidenavItem %} + diff --git a/templates/workspace_members.html.to b/templates/workspace_members.html similarity index 92% rename from templates/workspace_members.html.to rename to templates/workspace_members.html index 0f538b05..989d1d0e 100644 --- a/templates/workspace_members.html.to +++ b/templates/workspace_members.html @@ -1,15 +1,17 @@ -{% extends "base_workspace.html.to" %} +{% from "components.html" import EmptyState %} + +{% extends "base_workspace.html" %} {% block workspace_content %} {% if not members %} - {% module EmptyState( + {{ EmptyState( 'There are currently no members in this Workspace.', actionLabel='Invite a new Member', actionHref='/members/new', icon='avatar' - )%} + )}} {% else %} @@ -59,17 +61,17 @@ {% for m in members %} {{ m['first_name'] }} {{ m['last_name'] }} - {% if m['num_projects'] == '0' %} No Project Access {% end %} + {% if m['num_projects'] == '0' %} No Project Access {% endif %} {{ m['status'] }} {{ m['workspace_role'] }} - {% end %} + {% endfor %}
    -{% end %} +{% endif %} -{% end %} +{% endblock %} diff --git a/templates/workspace_projects.html.to b/templates/workspace_projects.html similarity index 72% rename from templates/workspace_projects.html.to rename to templates/workspace_projects.html index a9f1a8aa..91826bb6 100644 --- a/templates/workspace_projects.html.to +++ b/templates/workspace_projects.html @@ -1,13 +1,15 @@ -{% extends "base_workspace.html.to" %} +{% from "components.html" import Icon %} + +{% extends "base_workspace.html" %} {% block workspace_content %} {% for project in projects %}
    -

    {{ project['name'] }} ({{ len(project['environments'])}} environments)

    +

    {{ project['name'] }} ({{ project['environments']|length }} environments)

    - {% module Icon('edit') %} + {{ Icon('edit') }} edit
    @@ -15,7 +17,7 @@ {% for environment in project['environments'] %}
  • - {% module Icon('link') %} + {{ Icon('link') }} {{ environment["name"]}} @@ -24,10 +26,10 @@ members
  • - {% end %} + {% endfor %} -{% end %} +{% endfor %} -{% end %} +{% endblock %} diff --git a/templates/workspaces.html.to b/templates/workspaces.html similarity index 91% rename from templates/workspaces.html.to rename to templates/workspaces.html index 21bbad7d..5f407766 100644 --- a/templates/workspaces.html.to +++ b/templates/workspaces.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %}
    @@ -23,9 +23,9 @@ {{ w['user_count'] }}Users - {% end %} + {% endfor %}
    -{% end %} +{% endblock %} From fbe5137188c5e8c3c7aff7cac8cd97b97af161ba Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 1 Aug 2018 14:17:43 -0400 Subject: [PATCH 073/173] Requests index rendering --- Pipfile | 1 + Pipfile.lock | 10 +++- atst/app.py | 9 +++- atst/domain/requests.py | 45 ++++++++-------- atst/routes/__init__.py | 3 ++ atst/routes/requests.py | 52 +++++++++++++++++++ templates/components.html | 50 +++++++++++++++++- templates/{requests.html.to => requests.html} | 36 +++++++------ 8 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 atst/routes/requests.py rename templates/{requests.html.to => requests.html} (81%) diff --git a/Pipfile b/Pipfile index 4110ccbf..620553f1 100644 --- a/Pipfile +++ b/Pipfile @@ -16,6 +16,7 @@ alembic = "*" flask = "*" flask-sqlalchemy = "*" flask-assets = "*" +flask-session = "*" [dev-packages] bandit = "*" diff --git a/Pipfile.lock b/Pipfile.lock index d6e5cf64..d55c6fcf 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2ee6dd90ff3784e7b1781c680d690ac59118b4e3d72e8da3adf9e93d6e512bc7" + "sha256": "f097384512537988c799b892830b52e78bcc19133327213e9c6e2876210d62d3" }, "pipfile-spec": 6, "requires": { @@ -46,6 +46,14 @@ "index": "pypi", "version": "==0.12" }, + "flask-session": { + "hashes": [ + "sha256:a31c27e0c3287f00c825b3d9625aba585f4df4cccedb1e7dd5a69a215881a731", + "sha256:b9b32126bfc52c3169089f2ed9a40e34b589527bda48b633428e07d39d9c8792" + ], + "index": "pypi", + "version": "==0.3.1" + }, "flask-sqlalchemy": { "hashes": [ "sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b", diff --git a/atst/app.py b/atst/app.py index 087277fc..7dac78b7 100644 --- a/atst/app.py +++ b/atst/app.py @@ -2,15 +2,18 @@ import os import re from configparser import ConfigParser from redis import StrictRedis -from flask import Flask, request, g +from flask import Flask, request, g, session from unipath import Path from atst.api_client import ApiClient from atst.sessions import RedisSessions from atst.database import db from atst.assets import assets + from atst.routes import bp from atst.routes.workspaces import bp as workspace_routes +from atst.routes.requests import requests_bp + ENV = os.getenv("TORNADO_ENV", "dev") @@ -33,6 +36,7 @@ def make_app(config): app.register_blueprint(bp) app.register_blueprint(workspace_routes) + app.register_blueprint(requests_bp) return app @@ -48,7 +52,8 @@ def make_flask_callbacks(app): "id": "cce17030-4109-4719-b958-ed109dbb87c8", "first_name": "Amanda", "last_name": "Adamson", - "atat_role": "default" + "atat_role": "default", + "atat_permissions": [] } # TODO: Make me a macro diff --git a/atst/domain/requests.py b/atst/domain/requests.py index aa37b932..a513d660 100644 --- a/atst/domain/requests.py +++ b/atst/domain/requests.py @@ -4,6 +4,8 @@ from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm.attributes import flag_modified from atst.models import Request, RequestStatusEvent +from atst.database import db + from .exceptions import NotFoundError @@ -28,67 +30,68 @@ def deep_merge(source, destination: dict): class Requests(object): AUTO_APPROVE_THRESHOLD = 1000000 - def __init__(self, db_session): - self.db_session = db_session - - def create(self, creator_id, body): + @classmethod + def create(cls, creator_id, body): request = Request(creator=creator_id, body=body) status_event = RequestStatusEvent(new_status="incomplete") request.status_events.append(status_event) - self.db_session.add(request) - self.db_session.commit() + db.session.add(request) + db.session.commit() return request - def exists(self, request_id, creator_id): - return self.db_session.query( + @classmethod + def exists(cls, request_id, creator_id): + return db.session.query( exists().where( and_(Request.id == request_id, Request.creator == creator_id) ) ).scalar() - def get(self, request_id): + @classmethod + def get(cls, request_id): try: - request = self.db_session.query(Request).filter_by(id=request_id).one() + request = db.session.query(Request).filter_by(id=request_id).one() except NoResultFound: raise NotFoundError("request") return request - def get_many(self, creator_id=None): + @classmethod + def get_many(cls, creator_id=None): filters = [] if creator_id: filters.append(Request.creator == creator_id) requests = ( - self.db_session.query(Request) + db.session.query(Request) .filter(*filters) .order_by(Request.time_created.desc()) .all() ) return requests - @tornado.gen.coroutine - def submit(self, request): + @classmethod + def submit(cls, request): request.status_events.append(RequestStatusEvent(new_status="submitted")) if Requests.should_auto_approve(request): request.status_events.append(RequestStatusEvent(new_status="approved")) - self.db_session.add(request) - self.db_session.commit() + db.session.add(request) + db.session.commit() return request - @tornado.gen.coroutine - def update(self, request_id, request_delta): + @classmethod + def update(cls, request_id, request_delta): try: # Query for request matching id, acquiring a row-level write lock. # https://www.postgresql.org/docs/10/static/sql-select.html#SQL-FOR-UPDATE-SHARE request = ( - self.db_session.query(Request) + db.session.query(Request) .filter_by(id=request_id) .with_for_update(of=Request) .one() @@ -105,8 +108,8 @@ class Requests(object): # since it doesn't track dictionary mutations by default. flag_modified(request, "body") - self.db_session.add(request) - self.db_session.commit() + db.session.add(request) + db.session.commit() @classmethod def should_auto_approve(cls, request): diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py index 93fde8e2..de181ce2 100644 --- a/atst/routes/__init__.py +++ b/atst/routes/__init__.py @@ -1,4 +1,7 @@ from flask import Blueprint, render_template, g +import pendulum + +from atst.domain.requests import Requests bp = Blueprint("atst", __name__) diff --git a/atst/routes/requests.py b/atst/routes/requests.py new file mode 100644 index 00000000..6c37344d --- /dev/null +++ b/atst/routes/requests.py @@ -0,0 +1,52 @@ +from flask import Blueprint, g, render_template +import pendulum + +from atst.domain.requests import Requests + +requests_bp = Blueprint("requests", __name__) + +def map_request(user, request): + time_created = pendulum.instance(request.time_created) + is_new = time_created.add(days=1) > pendulum.now() + + return { + "order_id": request.id, + "is_new": is_new, + "status": request.status, + "app_count": 1, + "date": time_created.format("M/DD/YYYY"), + "full_name": "{} {}".format(user["first_name"], user["last_name"]), + } + + +@requests_bp.route("/requests", methods=["GET"]) +def requests_index(): + requests = [] + if "review_and_approve_jedi_workspace_request" in g.current_user["atat_permissions"]: + requests = Requests.get_many() + else: + requests = Requests.get_many(creator_id=g.current_user["id"]) + + mapped_requests = [map_request(g.current_user, r) for r in requests] + + return render_template("requests.html", requests=mapped_requests) + + +@requests_bp.route("/requests/new/", methods=["GET"]) +def requests_new(): + pass + + +@requests_bp.route("/requests/new//", methods=["GET"]) +def requests_form_update(): + pass + + +@requests_bp.route("/requests/verify/", methods=["GET"]) +def financial_verification(): + pass + + +@requests_bp.route("/requests/verify/", methods=["POST"]) +def update_financial_verification(): + pass diff --git a/templates/components.html b/templates/components.html index 0bc83991..04f6be36 100644 --- a/templates/components.html +++ b/templates/components.html @@ -31,7 +31,17 @@ {%- endmacro %} -{% macro EmptyState(self, message, actionLabel, actionHref, icon=None) -%} +{% macro Modal() -%} + +{%- endmacro %} + +{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%}

    {{ message }}

    @@ -42,3 +52,41 @@ {{ actionLabel }}
    {%- endmacro %} + +{% macro Alert(title, message=None, actions=None, level='info') -%} +{% set role = 'alertdialog' if actions else 'alert' %} +{% set levels = { + 'warning': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'error': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'info': { + 'icon': 'info', + 'tone': 'polite' + }, + 'success': { + 'icon': 'ok', + 'tone': 'polite' + } +} %} + +
    + {{ Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') }} + +
    +

    {{title}}

    + + {% if message %} +
    {{ message | safe }}
    + {% endif %} + + {% if actions %} +
    {{ actions | safe }}
    + {% endif %} +
    +
    +{%- endmacro %} diff --git a/templates/requests.html.to b/templates/requests.html similarity index 81% rename from templates/requests.html.to rename to templates/requests.html index bd0c9e8c..5d27ff1e 100644 --- a/templates/requests.html.to +++ b/templates/requests.html @@ -1,8 +1,10 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} + +{% from "components.html" import Modal, Alert, EmptyState %} {% block modal %} - {% if modalOpen() %} - {% apply modal %} + {% if g.modalOpen %} + {% call Modal() %}

    Your request is now approved!

    @@ -17,34 +19,34 @@ usage in sync with your budget.

    - {% module Alert("You'll need these details: ", + {{ Alert("You'll need these details: ", message="

    Task Order Number

    Contracting Officer: Name, E-mail and Office

    " - ) %} + ) }} - {% end %} - {% end %} -{% end %} + {% endcall %} + {% endif %} +{% endblock %} {% block content %} {% if not requests %} - {% module EmptyState( + {{ EmptyState( 'There are currently no active requests for you to see.', actionLabel='Create a new JEDI Cloud Request', actionHref='/requests/new', icon='document' - )%} + ) }} {% else %} - {% module Alert('Pending Financial Verification', + {{ Alert('Pending Financial Verification', message="

    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.

    " - ) %} + ) }}
    @@ -84,10 +86,10 @@ {% for r in requests %} - {{ r['order_id'] }} + {{ r['order_id'] }} {% if r['is_new'] %}New - {% end %} + {% endif %} {{ r['date'] }} {{ r['full_name'] }} {{ r['app_count'] }} @@ -97,13 +99,13 @@ Approval - {% end %} + {% endfor %}
    -{% end %} +{% endif %} -{% end %} +{% endblock %} From 2618d92e12589bb29546dbe43ef21c68ae568df1 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 1 Aug 2018 16:25:08 -0400 Subject: [PATCH 074/173] Financial verification form rendering --- Pipfile | 1 + Pipfile.lock | 10 ++- atst/app.py | 1 + atst/forms/forms.py | 4 +- atst/routes/requests.py | 7 ++- config/base.ini | 1 + ...on.html.to => financial_verification.html} | 61 ++++++++++--------- templates/requests_new.html.to | 2 +- 8 files changed, 51 insertions(+), 36 deletions(-) rename templates/requests/{financial_verification.html.to => financial_verification.html} (87%) diff --git a/Pipfile b/Pipfile index 620553f1..04e23572 100644 --- a/Pipfile +++ b/Pipfile @@ -17,6 +17,7 @@ flask = "*" flask-sqlalchemy = "*" flask-assets = "*" flask-session = "*" +flask-wtf = "*" [dev-packages] bandit = "*" diff --git a/Pipfile.lock b/Pipfile.lock index d55c6fcf..5dcf8f6b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f097384512537988c799b892830b52e78bcc19133327213e9c6e2876210d62d3" + "sha256": "e04e11d9bd5c1dcc725de48b20902f5c416417e73774e557e45af7bd0c147ff5" }, "pipfile-spec": 6, "requires": { @@ -62,6 +62,14 @@ "index": "pypi", "version": "==2.3.2" }, + "flask-wtf": { + "hashes": [ + "sha256:5d14d55cfd35f613d99ee7cba0fc3fbbe63ba02f544d349158c14ca15561cc36", + "sha256:d9a9e366b32dcbb98ef17228e76be15702cd2600675668bca23f63a7947fd5ac" + ], + "index": "pypi", + "version": "==0.14.2" + }, "itsdangerous": { "hashes": [ "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" diff --git a/atst/app.py b/atst/app.py index 7dac78b7..babaff7a 100644 --- a/atst/app.py +++ b/atst/app.py @@ -229,6 +229,7 @@ def make_config(): OVERRIDE_CONFIG_FILENAME = os.getenv("OVERRIDE_CONFIG_FULLPATH") config = ConfigParser() + config.optionxform = str config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME] if OVERRIDE_CONFIG_FILENAME: diff --git a/atst/forms/forms.py b/atst/forms/forms.py index c3ea02c4..48f03295 100644 --- a/atst/forms/forms.py +++ b/atst/forms/forms.py @@ -1,9 +1,9 @@ import tornado from tornado.gen import Return -from wtforms_tornado import Form +from flask_wtf import FlaskForm -class ValidatedForm(Form): +class ValidatedForm(FlaskForm): @tornado.gen.coroutine def perform_extra_validation(self, *args, **kwargs): diff --git a/atst/routes/requests.py b/atst/routes/requests.py index 6c37344d..5903524c 100644 --- a/atst/routes/requests.py +++ b/atst/routes/requests.py @@ -2,6 +2,7 @@ from flask import Blueprint, g, render_template import pendulum from atst.domain.requests import Requests +from atst.forms.financial import FinancialForm requests_bp = Blueprint("requests", __name__) @@ -43,8 +44,10 @@ def requests_form_update(): @requests_bp.route("/requests/verify/", methods=["GET"]) -def financial_verification(): - pass +def financial_verification(request_id=None): + request = Requests.get(request_id) + form = FinancialForm(data=request.body.get('financial_verification')) + return render_template("requests/financial_verification.html", f=form) @requests_bp.route("/requests/verify/", methods=["POST"]) diff --git a/config/base.ini b/config/base.ini index e8be9197..fddfa26f 100644 --- a/config/base.ini +++ b/config/base.ini @@ -5,6 +5,7 @@ DEBUG = true AUTHNID_BASE_URL= https://localhost:8001 COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret +SECRET_KEY = change_me_into_something_secret CAC_URL = https://localhost:8001 PE_NUMBER_CSV_URL = http://c95e1ebb198426ee57b8-174bb05a294821bedbf46b6384fe9b1f.r31.cf5.rackcdn.com/penumbers.csv REDIS_URI = redis://localhost:6379 diff --git a/templates/requests/financial_verification.html.to b/templates/requests/financial_verification.html similarity index 87% rename from templates/requests/financial_verification.html.to rename to templates/requests/financial_verification.html index df5b12ab..0f0d8110 100644 --- a/templates/requests/financial_verification.html.to +++ b/templates/requests/financial_verification.html @@ -1,4 +1,4 @@ -{% extends "../base.html.to" %} +{% extends "base.html" %} {% block content %} @@ -14,15 +14,15 @@ {% block form_action %} -
    - {% end %} + + {% endblock %} - {% module xsrf_form_html() %} + {{ f.csrf_token }} {% block form %} - {% autoescape None %} + {% autoescape false %} {% if f.errors %} There were some errors, see below. - {% end %} + {% endif %}

    In order to get you access to the JEDI Cloud, we will need you to enter the details below that will help us verify and account for your Task Order.

    @@ -32,7 +32,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.uii_ids.label }} {{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }} @@ -40,7 +40,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.pe_id.label }} {{ f.pe_id(placeholder="Example: 0203752A") }} @@ -48,7 +48,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.treasury_code.label }} {{ f.treasury_code(placeholder="Example: 1200") }} @@ -56,7 +56,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.ba_code.label }} {{ f.ba_code(placeholder="Example: 02") }} @@ -64,7 +64,7 @@
    {{ e }}
    - {% end %} + {% endfor %} @@ -76,7 +76,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.lname_co.label }} {{ f.lname_co(placeholder="Contracting Officer last name") }} @@ -84,7 +84,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.email_co.label }} {{ f.email_co(placeholder="jane@mail.mil") }} @@ -92,7 +92,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.office_co.label }} {{ f.office_co(placeholder="Example: WHS") }} @@ -100,7 +100,7 @@
    {{ e }}
    - {% end %} + {% endfor %} @@ -113,7 +113,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.lname_cor.label }} {{ f.lname_cor(placeholder="Contracting Officer Representative last name") }} @@ -121,7 +121,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.email_cor.label }} {{ f.email_cor(placeholder="jane@mail.mil") }} @@ -129,7 +129,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.office_cor.label }} {{ f.office_cor(placeholder="Example: WHS") }} @@ -137,7 +137,7 @@
    {{ e }}
    - {% end %} + {% endfor %}

    ↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available) @@ -149,7 +149,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.funding_type_other.label }} {{ f.funding_type_other(placeholder="") }} @@ -157,7 +157,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_0001.label }} {{ f.clin_0001(placeholder="50,000") }} @@ -165,7 +165,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_0003.label }} {{ f.clin_0003(placeholder="13,000") }} @@ -173,7 +173,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_1001.label }} {{ f.clin_1001(placeholder="30,000") }} @@ -181,7 +181,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_1003.label }} {{ f.clin_1003(placeholder="7,000") }} @@ -189,7 +189,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_2001.label }} {{ f.clin_2001(placeholder="30,000") }} @@ -197,7 +197,7 @@
    {{ e }}
    - {% end %} + {% endfor %} {{ f.clin_2003.label }} {{ f.clin_2003(placeholder="7,000") }} @@ -205,15 +205,16 @@
    {{ e }}
    - {% end %} - {% end %} + {% endfor %} + {% endautoescape %} + {% endblock form %} {% block next %} - {% end %} + {% endblock %}
    -{% end %} +{% endblock %} diff --git a/templates/requests_new.html.to b/templates/requests_new.html.to index 5a309f26..c5f96ed5 100644 --- a/templates/requests_new.html.to +++ b/templates/requests_new.html.to @@ -22,7 +22,7 @@ {% end %} {% end %} - {% module xsrf_form_html() %} + {{ form.csrf_token }} {% block form %} form goes here {% end %} From f15fc19eafbce87af87dc54b1d76fc5f629f51a8 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 2 Aug 2018 10:21:26 -0400 Subject: [PATCH 075/173] First page of request form rendering, but flow is still WIP --- atst/handlers/request_new.py | 3 +- atst/routes/requests.py | 199 +++++++++++++++++- templates/components.html | 53 +++++ templates/requests/menu.html | 13 ++ templates/requests/menu.html.to | 13 -- templates/requests/screen-0.html | 12 ++ templates/requests/screen-0.html.to | 12 -- templates/requests/screen-1.html | 46 ++++ templates/requests/screen-1.html.to | 45 ---- templates/requests/screen-2.html | 32 +++ templates/requests/screen-2.html.to | 31 --- .../{screen-3.html.to => screen-3.html} | 0 .../{screen-4.html.to => screen-4.html} | 0 .../{screen-5.html.to => screen-5.html} | 0 .../{sidebar.html.to => sidebar.html} | 0 templates/requests_new.html | 45 ++++ templates/requests_new.html.to | 46 ---- 17 files changed, 398 insertions(+), 152 deletions(-) create mode 100644 templates/requests/menu.html delete mode 100644 templates/requests/menu.html.to create mode 100644 templates/requests/screen-0.html delete mode 100644 templates/requests/screen-0.html.to create mode 100644 templates/requests/screen-1.html delete mode 100644 templates/requests/screen-1.html.to create mode 100644 templates/requests/screen-2.html delete mode 100644 templates/requests/screen-2.html.to rename templates/requests/{screen-3.html.to => screen-3.html} (100%) rename templates/requests/{screen-4.html.to => screen-4.html} (100%) rename templates/requests/{screen-5.html.to => screen-5.html} (100%) rename templates/requests/{sidebar.html.to => sidebar.html} (100%) create mode 100644 templates/requests_new.html delete mode 100644 templates/requests_new.html.to diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 1d33daa0..30549e63 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -101,7 +101,6 @@ class RequestNew(BaseHandler): class JEDIRequestFlow(object): def __init__( self, - requests_repo, pe_numbers_repo, current_step, request=None, @@ -110,6 +109,8 @@ class JEDIRequestFlow(object): current_user=None, existing_request=None, ): + self.pe_numbers_repo = pe_numbers_repo + self.requests_repo = requests_repo self.pe_numbers_repo = pe_numbers_repo diff --git a/atst/routes/requests.py b/atst/routes/requests.py index 5903524c..565c268e 100644 --- a/atst/routes/requests.py +++ b/atst/routes/requests.py @@ -1,8 +1,14 @@ -from flask import Blueprint, g, render_template +from flask import Blueprint, g, render_template, url_for, redirect, request import pendulum +from collections import defaultdict from atst.domain.requests import Requests from atst.forms.financial import FinancialForm +from atst.forms.request import RequestForm +from atst.forms.org import OrgForm +from atst.forms.poc import POCForm +from atst.forms.review import ReviewForm + requests_bp = Blueprint("requests", __name__) @@ -34,13 +40,72 @@ def requests_index(): @requests_bp.route("/requests/new/", methods=["GET"]) -def requests_new(): +def requests_form_new(): pass @requests_bp.route("/requests/new//", methods=["GET"]) -def requests_form_update(): - pass +def requests_form_update(screen=1, request_id=None): + request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow(screen, request, request_id=request_id) + + return render_template( + "requests/screen-%d.html" % int(screen), + f=jedi_flow.form, + data=jedi_flow.current_step_data, + screens=jedi_flow.screens, + current=screen, + next_screen=screen + 1, + request_id=request_id, + can_submit=jedi_flow.can_submit + ) + +@requests_bp.route("/requests/new//", methods=["POST"]) +def requests_update(screen=1, request_id=None): + screen = int(screen) + post_data = str(request.data) + current_user = g.current_user + existing_request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow( + screen, + post_data=post_data, + request_id=request_id, + current_user=current_user, + existing_request=existing_request, + ) + + rerender_args = dict( + f=jedi_flow.form, + data=post_data, + screens=jedi_flow.screens, + current=screen, + next_screen=jedi_flow.next_screen, + request_id=jedi_flow.request_id, + ) + + if jedi_flow.validate(): + jedi_flow.create_or_update_request() + valid = jedi_flow.validate_warnings() + if valid: + if jedi_flow.next_screen > len(jedi_flow.screens): + where = "/requests" + else: + where = url_for( + "requests.requests_Form_update", screen=jedi_flow.next_screen, request_id=jedi_flow.request_id + ) + return redirect(where) + else: + return render_template( + "requests/screen-%d.html" % int(screen), + **rerender_args + ) + else: + return render_template( + "requests/screen-%d.html" % int(screen), + **rerender_args + ) + + @requests_bp.route("/requests/verify/", methods=["GET"]) @@ -53,3 +118,129 @@ def financial_verification(request_id=None): @requests_bp.route("/requests/verify/", methods=["POST"]) def update_financial_verification(): pass + + +class JEDIRequestFlow(object): + def __init__( + self, + current_step, + request=None, + post_data=None, + request_id=None, + current_user=None, + existing_request=None, + ): + self.current_step = current_step + self.request = request + + self.post_data = post_data + self.is_post = self.post_data is not None + + self.request_id = request_id + self.form = self._form() + + self.current_user = current_user + self.existing_request = existing_request + + def _form(self): + if self.is_post: + return self.form_class()(self.post_data) + elif self.request: + return self.form_class()(data=self.current_step_data) + else: + return self.form_class()() + + def validate(self): + return self.form.validate() + + def validate_warnings(self): + existing_request_data = ( + self.existing_request + and self.existing_request.body.get(self.form_section) + ) or None + + valid = self.form.perform_extra_validation( + existing_request_data, + ) + return valid + + @property + def current_screen(self): + return self.screens[self.current_step - 1] + + @property + def form_section(self): + return self.current_screen["section"] + + def form_class(self): + return self.current_screen["form"] + + @property + def current_step_data(self): + data = {} + + if self.is_post: + data = self.post_data + + if self.request: + if self.form_section == "review_submit": + data = self.request.body + else: + data = self.request.body.get(self.form_section, {}) + + return defaultdict(lambda: defaultdict(lambda: 'Input required'), data) + + @property + def can_submit(self): + return self.request and self.request.status != "incomplete" + + @property + def next_screen(self): + return self.current_step + 1 + + @property + def screens(self): + return [ + { + "title": "Details of Use", + "section": "details_of_use", + "form": RequestForm, + "subitems": [ + { + "title": "Overall request details", + "id": "overall-request-details", + }, + {"title": "Cloud Resources", "id": "cloud-resources"}, + {"title": "Support Staff", "id": "support-staff"}, + ], + "show": True, + }, + { + "title": "Information About You", + "section": "information_about_you", + "form": OrgForm, + "show": True, + }, + { + "title": "Primary Point of Contact", + "section": "primary_poc", + "form": POCForm, + "show": True, + }, + { + "title": "Review & Submit", + "section": "review_submit", + "form": ReviewForm, + "show":True, + }, + ] + + def create_or_update_request(self): + request_data = { + self.form_section: self.form.data + } + if self.request_id: + Requests.update(request_id, request_data) + else: + request = Requests.create(self.current_user["id"], request_data) + self.request_id = request.id diff --git a/templates/components.html b/templates/components.html index 04f6be36..027ede6f 100644 --- a/templates/components.html +++ b/templates/components.html @@ -90,3 +90,56 @@ {%- endmacro %} + +{% macro TextInput(field, placeholder='') -%} +
    + + + {{ field(placeholder=placeholder) | safe }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} +
    +{%- endmacro %} + +{% macro OptionsInput(field, inline=False) -%} +
    + +
    + + {{ field.label }} + + {% if field.description %} + {{ field.description | safe }} + {% endif %} + + {% if field.errors %} + {{ Icon('alert') }} + {% endif %} + + + {{ field() }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} + +
    +
    + +{%- endmacro %} diff --git a/templates/requests/menu.html b/templates/requests/menu.html new file mode 100644 index 00000000..f1642e46 --- /dev/null +++ b/templates/requests/menu.html @@ -0,0 +1,13 @@ +
    + +
    diff --git a/templates/requests/menu.html.to b/templates/requests/menu.html.to deleted file mode 100644 index 4bc77431..00000000 --- a/templates/requests/menu.html.to +++ /dev/null @@ -1,13 +0,0 @@ -
    - -
    \ No newline at end of file diff --git a/templates/requests/screen-0.html b/templates/requests/screen-0.html new file mode 100644 index 00000000..19f57d2e --- /dev/null +++ b/templates/requests/screen-0.html @@ -0,0 +1,12 @@ +{% extends '../requests_new.html.to' %} + +{% block form %} +

    New JEDI Request

    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus error omnis a, tenetur similique quo officiis voluptates eum recusandae dolorem minus dignissimos, magni consequatur, maxime debitis reprehenderit sint non iusto?

    + +New Application +Existing Application +Sandbox Environment + +{% endblock %} diff --git a/templates/requests/screen-0.html.to b/templates/requests/screen-0.html.to deleted file mode 100644 index 6fe78374..00000000 --- a/templates/requests/screen-0.html.to +++ /dev/null @@ -1,12 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block form %} -

    New JEDI Request

    - -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus error omnis a, tenetur similique quo officiis voluptates eum recusandae dolorem minus dignissimos, magni consequatur, maxime debitis reprehenderit sint non iusto?

    - -New Application -Existing Application -Sandbox Environment - -{% end %} diff --git a/templates/requests/screen-1.html b/templates/requests/screen-1.html new file mode 100644 index 00000000..da6c5ae0 --- /dev/null +++ b/templates/requests/screen-1.html @@ -0,0 +1,46 @@ +{% extends 'requests_new.html' %} + +{% from "components.html" import Alert, TextInput, OptionsInput %} + +{% block subtitle %} +

    Details of Use

    +{% endblock %} + +{% block form %} + +{% if f.errors %} + {{ Alert('There were some errors', + message="

    Please see below.

    ", + level='error' + ) }} +{% endif %} + + +

    We’d like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.

    +

    All fields are required, unless specified optional.

    + +

    General

    +{{ TextInput(f.dod_component) }} +{{ TextInput(f.jedi_usage,placeholder="e.g. We are migrating XYZ application to the cloud so that...") }} + +

    Cloud Readiness

    +{{ TextInput(f.num_software_systems,placeholder="Number of systems") }} +{{ OptionsInput(f.jedi_migration) }} +{{ OptionsInput(f.rationalization_software_systems) }} +{{ OptionsInput(f.technical_support_team) }} +{{ OptionsInput(f.organization_providing_assistance) }} +{{ OptionsInput(f.engineering_assessment) }} +{{ TextInput(f.data_transfers) }} +{{ TextInput(f.expected_completion_date) }} +{{ OptionsInput(f.cloud_native) }} + +

    Financial Usage

    +{{ TextInput(f.estimated_monthly_spend) }} +

    So this means you are spending approximately $X annually

    +{{ TextInput(f.dollar_value) }} +{{ TextInput(f.number_user_sessions) }} +{{ TextInput(f.average_daily_traffic) }} +{{ TextInput(f.start_date) }} + + +{% endblock %} diff --git a/templates/requests/screen-1.html.to b/templates/requests/screen-1.html.to deleted file mode 100644 index a8ed7887..00000000 --- a/templates/requests/screen-1.html.to +++ /dev/null @@ -1,45 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block subtitle %} -

    Details of Use

    -{% end %} - -{% block form %} - -{% autoescape None %} -{% if f.errors %} - {% module Alert('There were some errors', - message="

    Please see below.

    ", - level='error' - ) %} -{% end %} - - -

    We’d like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.

    -

    All fields are required, unless specified optional.

    - -

    General

    -{% module TextInput(f.dod_component) %} -{% module TextInput(f.jedi_usage,placeholder="e.g. We are migrating XYZ application to the cloud so that...") %} - -

    Cloud Readiness

    -{% module TextInput(f.num_software_systems,placeholder="Number of systems") %} -{% module OptionsInput(f.jedi_migration) %} -{% module OptionsInput(f.rationalization_software_systems) %} -{% module OptionsInput(f.technical_support_team) %} -{% module OptionsInput(f.organization_providing_assistance) %} -{% module OptionsInput(f.engineering_assessment) %} -{% module TextInput(f.data_transfers) %} -{% module TextInput(f.expected_completion_date) %} -{% module OptionsInput(f.cloud_native) %} - -

    Financial Usage

    -{% module TextInput(f.estimated_monthly_spend) %} -

    So this means you are spending approximately $X annually

    -{% module TextInput(f.dollar_value) %} -{% module TextInput(f.number_user_sessions) %} -{% module TextInput(f.average_daily_traffic) %} -{% module TextInput(f.start_date) %} - - -{% end %} diff --git a/templates/requests/screen-2.html b/templates/requests/screen-2.html new file mode 100644 index 00000000..24c8f749 --- /dev/null +++ b/templates/requests/screen-2.html @@ -0,0 +1,32 @@ +{% extends 'requests_new.html' %} + +{% from "components.html" import Alert, TextInput, OptionsInput %} + +{% block subtitle %} +

    Information About You

    +{% endblock %} + +{% block form %} + +{% if f.errors %} + {{ Alert('There were some errors', + message="

    Please see below.

    ", + level='error' + ) }} +{% endif %} + +

    Please tell us more about you.

    + +{{ TextInput(f.fname_request,placeholder='First Name') }} +{{ TextInput(f.lname_request,placeholder='Last Name') }} +{{ TextInput(f.email_request,placeholder='jane@mail.mil') }} +{{ TextInput(f.phone_number,placeholder='(123) 456-7890') }} + +

    We want to collect the following information from you for security auditing and determining priviledged user access

    + +{{ TextInput(f.service_branch,placeholder='e.g. US Air Force, US Army, US Navy, Marine Corps, Defense Media Agency') }} +{{ OptionsInput(f.citizenship) }} +{{ OptionsInput(f.designation) }} +{{ TextInput(f.date_latest_training) }} + +{% endblock %} diff --git a/templates/requests/screen-2.html.to b/templates/requests/screen-2.html.to deleted file mode 100644 index fb667dc5..00000000 --- a/templates/requests/screen-2.html.to +++ /dev/null @@ -1,31 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block subtitle %} -

    Information About You

    -{% end %} - -{% block form %} - -{% autoescape None %} -{% if f.errors %} - {% module Alert('There were some errors', - message="

    Please see below.

    ", - level='error' - ) %} -{% end %} - -

    Please tell us more about you.

    - -{% module TextInput(f.fname_request,placeholder='First Name') %} -{% module TextInput(f.lname_request,placeholder='Last Name') %} -{% module TextInput(f.email_request,placeholder='jane@mail.mil') %} -{% module TextInput(f.phone_number,placeholder='(123) 456-7890') %} - -

    We want to collect the following information from you for security auditing and determining priviledged user access

    - -{% module TextInput(f.service_branch,placeholder='e.g. US Air Force, US Army, US Navy, Marine Corps, Defense Media Agency') %} -{% module OptionsInput(f.citizenship) %} -{% module OptionsInput(f.designation) %} -{% module TextInput(f.date_latest_training) %} - -{% end %} \ No newline at end of file diff --git a/templates/requests/screen-3.html.to b/templates/requests/screen-3.html similarity index 100% rename from templates/requests/screen-3.html.to rename to templates/requests/screen-3.html diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html similarity index 100% rename from templates/requests/screen-4.html.to rename to templates/requests/screen-4.html diff --git a/templates/requests/screen-5.html.to b/templates/requests/screen-5.html similarity index 100% rename from templates/requests/screen-5.html.to rename to templates/requests/screen-5.html diff --git a/templates/requests/sidebar.html.to b/templates/requests/sidebar.html similarity index 100% rename from templates/requests/sidebar.html.to rename to templates/requests/sidebar.html diff --git a/templates/requests_new.html b/templates/requests_new.html new file mode 100644 index 00000000..559c2355 --- /dev/null +++ b/templates/requests_new.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} + +{% block content %} + +
    + + {% include 'requests/menu.html' %} + +
    + +
    +

    New Request

    +
    {% block subtitle %}{% endblock %}
    +
    + +
    + {% block form_action %} + {% if request_id %} +
    + {% else %} + + {% endif %} + {% endblock %} + + {{ f.csrf_token }} + {% block form %} + form goes here + {% endblock %} + +
    + +
    + + {% block next %} + +
    + +
    + + {% endblock %} + + +
    + +{% endblock %} diff --git a/templates/requests_new.html.to b/templates/requests_new.html.to deleted file mode 100644 index c5f96ed5..00000000 --- a/templates/requests_new.html.to +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "base.html.to" %} - -{% block content %} - -
    - - {% include 'requests/menu.html.to' %} - -
    - -
    -

    New Request

    -
    {% block subtitle %}{% end %}
    -
    - -
    - {% block form_action %} - {% if request_id %} -
    - {% else %} - - {% end %} - {% end %} - - {{ form.csrf_token }} - {% block form %} - form goes here - {% end %} - -
    - -
    - - {% block next %} - -
    - -
    - - {% end %} - - -
    - -{% end %} - From a032ccd5b012fa49c043c6749a48a8e15adf1149 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 2 Aug 2018 10:36:25 -0400 Subject: [PATCH 076/173] Converted all form pages. Flow still not working --- atst/forms/financial.py | 4 +-- atst/forms/forms.py | 5 ++-- atst/routes/requests.py | 11 +++++-- templates/requests/screen-3.html | 23 +++++++------- templates/requests/screen-4.html | 33 +++++++++++---------- templates/requests/screen-5.html | 51 ++++++++++++++++---------------- 6 files changed, 65 insertions(+), 62 deletions(-) diff --git a/atst/forms/financial.py b/atst/forms/financial.py index 52b4ef28..fb66282b 100644 --- a/atst/forms/financial.py +++ b/atst/forms/financial.py @@ -36,7 +36,6 @@ def suggest_pe_id(pe_id): return None -@tornado.gen.coroutine def validate_pe_id(field, existing_request, pe_numbers_repo): try: pe_number = pe_numbers_repo.get(field.data) @@ -55,12 +54,11 @@ def validate_pe_id(field, existing_request, pe_numbers_repo): class FinancialForm(ValidatedForm): - @tornado.gen.coroutine def perform_extra_validation(self, existing_request, pe_numbers_repo): valid = True if not existing_request or existing_request.get('pe_id') != self.pe_id.data: valid = yield validate_pe_id(self.pe_id, existing_request, pe_numbers_repo) - raise Return(valid) + return valid task_order_id = StringField( "Task Order Number associated with this request.", validators=[Required()] diff --git a/atst/forms/forms.py b/atst/forms/forms.py index 48f03295..d60e3a2c 100644 --- a/atst/forms/forms.py +++ b/atst/forms/forms.py @@ -5,8 +5,7 @@ from flask_wtf import FlaskForm class ValidatedForm(FlaskForm): - @tornado.gen.coroutine def perform_extra_validation(self, *args, **kwargs): - """A coroutine that performs any applicable extra validation. Must + """Performs any applicable extra validation. Must return True if the form is valid or False otherwise.""" - raise Return(True) + return True diff --git a/atst/routes/requests.py b/atst/routes/requests.py index 565c268e..0c225a7f 100644 --- a/atst/routes/requests.py +++ b/atst/routes/requests.py @@ -63,7 +63,7 @@ def requests_form_update(screen=1, request_id=None): @requests_bp.route("/requests/new//", methods=["POST"]) def requests_update(screen=1, request_id=None): screen = int(screen) - post_data = str(request.data) + post_data = request.form current_user = g.current_user existing_request = Requests.get(request_id) if request_id is not None else None jedi_flow = JEDIRequestFlow( @@ -91,7 +91,7 @@ def requests_update(screen=1, request_id=None): where = "/requests" else: where = url_for( - "requests.requests_Form_update", screen=jedi_flow.next_screen, request_id=jedi_flow.request_id + "requests.requests_form_update", screen=jedi_flow.next_screen, request_id=jedi_flow.request_id ) return redirect(where) else: @@ -120,6 +120,11 @@ def update_financial_verification(): pass +@requests_bp.route("/requests/submit/", methods=["POST"]) +def requests_submit(request_id=None): + pass + + class JEDIRequestFlow(object): def __init__( self, @@ -240,7 +245,7 @@ class JEDIRequestFlow(object): self.form_section: self.form.data } if self.request_id: - Requests.update(request_id, request_data) + Requests.update(self.request_id, request_data) else: request = Requests.create(self.current_user["id"], request_data) self.request_id = request.id diff --git a/templates/requests/screen-3.html b/templates/requests/screen-3.html index af4ea66f..5bdbaf43 100644 --- a/templates/requests/screen-3.html +++ b/templates/requests/screen-3.html @@ -1,18 +1,19 @@ -{% extends '../requests_new.html.to' %} +{% extends 'requests_new.html' %} + +{% from "components.html" import Alert, TextInput %} {% block subtitle %}

    Primary Government/Military
    Point of Contact (POC)

    -{% end %} +{% endblock %} {% block form %} -{% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please see below.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}

    Please designate a Primary Point of Contact that will be responsible for owning the workspace in the JEDI Cloud.

    The Point of Contact will become the primary owner of the workspace created to use the JEDI Cloud. As a workspace owner, this person will have the ability to: @@ -26,9 +27,9 @@ This POC may be you.

    -{% module TextInput(f.fname_poc,placeholder='First Name') %} -{% module TextInput(f.lname_poc,placeholder='Last Name') %} -{% module TextInput(f.email_poc,placeholder='jane@mail.mil') %} -{% module TextInput(f.dodid_poc,placeholder='10-digit number on the back of the CAC') %} +{{ TextInput(f.fname_poc,placeholder='First Name') }} +{{ TextInput(f.lname_poc,placeholder='Last Name') }} +{{ TextInput(f.email_poc,placeholder='jane@mail.mil') }} +{{ TextInput(f.dodid_poc,placeholder='10-digit number on the back of the CAC') }} -{% end %} \ No newline at end of file +{% endblock %} diff --git a/templates/requests/screen-4.html b/templates/requests/screen-4.html index 60dd06ac..37cfc5de 100644 --- a/templates/requests/screen-4.html +++ b/templates/requests/screen-4.html @@ -1,27 +1,28 @@ -{% extends '../requests_new.html.to' %} +{% extends 'requests_new.html' %} + +{% from "components.html" import Alert, TextInput %} {% block subtitle %}

    Review & Submit

    -{% end %} +{% endblock %} {% block form_action %} -
    - {% end %} + +{% endblock %} {% block form %} - {% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all required fields before submitting.

    ", level='error' - ) %} - {% end %} + ) }} + {% endif %}

    Before you can submit your request, please take a moment to review the information entered in the form. You may make changes by clicking the edit link on each section. When all information looks right, go ahead and submit.

    -

    Details of Use Edit

    +

    Details of Use Edit

    @@ -107,7 +108,7 @@
    -

    Information About You Edit

    +

    Information About You Edit

    @@ -152,7 +153,7 @@
    -

    Primary Point of Contact Edit

    +

    Primary Point of Contact Edit

    @@ -178,15 +179,15 @@ -{% end %} +{% endblock %} {% block next %} {% if not can_submit %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all required fields before submitting.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}
    @@ -194,4 +195,4 @@ -{% end %} +{% endblock %} diff --git a/templates/requests/screen-5.html b/templates/requests/screen-5.html index e8642f1e..845ed133 100644 --- a/templates/requests/screen-5.html +++ b/templates/requests/screen-5.html @@ -2,13 +2,12 @@ {% block form %} -{% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all the fields before submitting.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}

    Financial Verification

    @@ -20,7 +19,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.uii_ids.label }} {{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }} @@ -28,7 +27,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.pe_id.label }} {{ f.pe_id(placeholder="Example: 0203752A") }} @@ -36,7 +35,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.treasury_code.label }} {{ f.treasury_code(placeholder="Example: 1200") }} @@ -44,7 +43,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.ba_code.label }} {{ f.ba_code(placeholder="Example: 02") }} @@ -52,7 +51,7 @@
    {{ e }}
    -{% end %} +{% endfor %} @@ -64,7 +63,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.lname_co.label }} {{ f.lname_co(placeholder="Contracting Officer last name") }} @@ -72,7 +71,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.email_co.label }} {{ f.email_co(placeholder="jane@mail.mil") }} @@ -80,7 +79,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.office_co.label }} {{ f.office_co(placeholder="Example: WHS") }} @@ -88,7 +87,7 @@
    {{ e }}
    -{% end %} +{% endfor %} @@ -101,7 +100,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.lname_cor.label }} {{ f.lname_cor(placeholder="Contracting Officer Representative last name") }} @@ -109,7 +108,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.email_cor.label }} {{ f.email_cor(placeholder="jane@mail.mil") }} @@ -117,7 +116,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.office_cor.label }} {{ f.office_cor(placeholder="Example: WHS") }} @@ -125,7 +124,7 @@
    {{ e }}
    -{% end %} +{% endfor %}

    ↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available) @@ -137,7 +136,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.funding_type_other.label }} {{ f.funding_type_other(placeholder="") }} @@ -145,7 +144,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_0001.label }} {{ f.clin_0001(placeholder="50,000") }} @@ -153,7 +152,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_0003.label }} {{ f.clin_0003(placeholder="13,000") }} @@ -161,7 +160,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_1001.label }} {{ f.clin_1001(placeholder="30,000") }} @@ -169,7 +168,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_1003.label }} {{ f.clin_1003(placeholder="7,000") }} @@ -177,7 +176,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_2001.label }} {{ f.clin_2001(placeholder="30,000") }} @@ -185,7 +184,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_2003.label }} {{ f.clin_2003(placeholder="7,000") }} @@ -193,7 +192,7 @@
    {{ e }}
    -{% end %} +{% endfor %} -{% end %} +{% endblock %} From 46e3bf1643a404bcd82f4b17f2426458c5248a9b Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 2 Aug 2018 10:59:05 -0400 Subject: [PATCH 077/173] Request flow seems to be working --- atst/app.py | 2 +- atst/routes/requests/__init__.py | 126 ++++++++++++++++++++ atst/routes/requests/jedi_request_flow.py | 135 ++++++++++++++++++++++ templates/components.html | 6 +- templates/requests/menu.html | 2 +- 5 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 atst/routes/requests/__init__.py create mode 100644 atst/routes/requests/jedi_request_flow.py diff --git a/atst/app.py b/atst/app.py index babaff7a..cd432ea9 100644 --- a/atst/app.py +++ b/atst/app.py @@ -46,7 +46,7 @@ def make_flask_callbacks(app): def set_globals(): g.navigationContext = 'workspace' if re.match('\/workspaces\/[A-Za-z0-9]*', request.url) else 'global' g.dev = os.getenv("TORNADO_ENV", "dev") == "dev" - g.matchesPath = lambda href: re.match('^'+href, request.url) + g.matchesPath = lambda href: re.match('^'+href, request.path) g.modalOpen = request.args.get("modal", False) g.current_user = { "id": "cce17030-4109-4719-b958-ed109dbb87c8", diff --git a/atst/routes/requests/__init__.py b/atst/routes/requests/__init__.py new file mode 100644 index 00000000..aa747e71 --- /dev/null +++ b/atst/routes/requests/__init__.py @@ -0,0 +1,126 @@ +from flask import Blueprint, g, render_template, url_for, redirect, request +import pendulum + +from atst.routes.requests.jedi_request_flow import JEDIRequestFlow +from atst.domain.requests import Requests + + +requests_bp = Blueprint("requests", __name__) + +def map_request(user, request): + time_created = pendulum.instance(request.time_created) + is_new = time_created.add(days=1) > pendulum.now() + + return { + "order_id": request.id, + "is_new": is_new, + "status": request.status, + "app_count": 1, + "date": time_created.format("M/DD/YYYY"), + "full_name": "{} {}".format(user["first_name"], user["last_name"]), + } + + +@requests_bp.route("/requests", methods=["GET"]) +def requests_index(): + requests = [] + if "review_and_approve_jedi_workspace_request" in g.current_user["atat_permissions"]: + requests = Requests.get_many() + else: + requests = Requests.get_many(creator_id=g.current_user["id"]) + + mapped_requests = [map_request(g.current_user, r) for r in requests] + + return render_template("requests.html", requests=mapped_requests) + + +@requests_bp.route("/requests/new/", methods=["GET"]) +def requests_form_new(): + pass + + +@requests_bp.route("/requests/new//", methods=["GET"]) +def requests_form_update(screen=1, request_id=None): + request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow(screen, request, request_id=request_id) + + return render_template( + "requests/screen-%d.html" % int(screen), + f=jedi_flow.form, + data=jedi_flow.current_step_data, + screens=jedi_flow.screens, + current=screen, + next_screen=screen + 1, + request_id=request_id, + can_submit=jedi_flow.can_submit + ) + +@requests_bp.route("/requests/new//", methods=["POST"]) +def requests_update(screen=1, request_id=None): + screen = int(screen) + post_data = request.form + current_user = g.current_user + existing_request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow( + screen, + post_data=post_data, + request_id=request_id, + current_user=current_user, + existing_request=existing_request, + ) + + rerender_args = dict( + f=jedi_flow.form, + data=post_data, + screens=jedi_flow.screens, + current=screen, + next_screen=jedi_flow.next_screen, + request_id=jedi_flow.request_id, + ) + + if jedi_flow.validate(): + jedi_flow.create_or_update_request() + valid = jedi_flow.validate_warnings() + if valid: + if jedi_flow.next_screen > len(jedi_flow.screens): + where = "/requests" + else: + where = url_for( + "requests.requests_form_update", screen=jedi_flow.next_screen, request_id=jedi_flow.request_id + ) + return redirect(where) + else: + return render_template( + "requests/screen-%d.html" % int(screen), + **rerender_args + ) + else: + return render_template( + "requests/screen-%d.html" % int(screen), + **rerender_args + ) + + + + +@requests_bp.route("/requests/verify/", methods=["GET"]) +def financial_verification(request_id=None): + request = Requests.get(request_id) + form = FinancialForm(data=request.body.get('financial_verification')) + return render_template("requests/financial_verification.html", f=form) + + +@requests_bp.route("/requests/verify/", methods=["POST"]) +def update_financial_verification(): + pass + + +@requests_bp.route("/requests/submit/", methods=["POST"]) +def requests_submit(request_id=None): + request = Requests.get(request_id) + Requests.submit(request) + + if request.status == "approved": + return redirect("/requests?modal=True") + else: + return redirect("/requests") diff --git a/atst/routes/requests/jedi_request_flow.py b/atst/routes/requests/jedi_request_flow.py new file mode 100644 index 00000000..4befe5f5 --- /dev/null +++ b/atst/routes/requests/jedi_request_flow.py @@ -0,0 +1,135 @@ +from collections import defaultdict + +from atst.domain.requests import Requests +from atst.forms.financial import FinancialForm +from atst.forms.request import RequestForm +from atst.forms.org import OrgForm +from atst.forms.poc import POCForm +from atst.forms.review import ReviewForm + + + +class JEDIRequestFlow(object): + def __init__( + self, + current_step, + request=None, + post_data=None, + request_id=None, + current_user=None, + existing_request=None, + ): + self.current_step = current_step + self.request = request + + self.post_data = post_data + self.is_post = self.post_data is not None + + self.request_id = request_id + self.form = self._form() + + self.current_user = current_user + self.existing_request = existing_request + + def _form(self): + if self.is_post: + return self.form_class()(self.post_data) + elif self.request: + return self.form_class()(data=self.current_step_data) + else: + return self.form_class()() + + def validate(self): + return self.form.validate() + + def validate_warnings(self): + existing_request_data = ( + self.existing_request + and self.existing_request.body.get(self.form_section) + ) or None + + valid = self.form.perform_extra_validation( + existing_request_data, + ) + return valid + + @property + def current_screen(self): + return self.screens[self.current_step - 1] + + @property + def form_section(self): + return self.current_screen["section"] + + def form_class(self): + return self.current_screen["form"] + + @property + def current_step_data(self): + data = {} + + if self.is_post: + data = self.post_data + + if self.request: + if self.form_section == "review_submit": + data = self.request.body + else: + data = self.request.body.get(self.form_section, {}) + + return defaultdict(lambda: defaultdict(lambda: 'Input required'), data) + + @property + def can_submit(self): + return self.request and self.request.status != "incomplete" + + @property + def next_screen(self): + return self.current_step + 1 + + @property + def screens(self): + return [ + { + "title": "Details of Use", + "section": "details_of_use", + "form": RequestForm, + "subitems": [ + { + "title": "Overall request details", + "id": "overall-request-details", + }, + {"title": "Cloud Resources", "id": "cloud-resources"}, + {"title": "Support Staff", "id": "support-staff"}, + ], + "show": True, + }, + { + "title": "Information About You", + "section": "information_about_you", + "form": OrgForm, + "show": True, + }, + { + "title": "Primary Point of Contact", + "section": "primary_poc", + "form": POCForm, + "show": True, + }, + { + "title": "Review & Submit", + "section": "review_submit", + "form": ReviewForm, + "show":True, + }, + ] + + def create_or_update_request(self): + request_data = { + self.form_section: self.form.data + } + if self.request_id: + Requests.update(self.request_id, request_data) + else: + request = Requests.create(self.current_user["id"], request_data) + self.request_id = request.id diff --git a/templates/components.html b/templates/components.html index 027ede6f..ea214631 100644 --- a/templates/components.html +++ b/templates/components.html @@ -7,11 +7,11 @@ {% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%}
  • - {% if icon %} + {% if icon %} {{ Icon(icon, classes="sidenav__link-icon") }} - {% endif %} + {% endif %} - {{label}} + {{label}} {% if subnav and active %} diff --git a/templates/requests/menu.html b/templates/requests/menu.html index f1642e46..24b28d4f 100644 --- a/templates/requests/menu.html +++ b/templates/requests/menu.html @@ -2,7 +2,7 @@
  • - {% end %} - {% end %} -{% end %} + {% endcall %} + {% endif %} +{% endblock %} {% block content %} -{% module Alert('A Warning Alert', +{{ Alert('A Warning Alert', message="\

    This is a message. It is a very important message. Please note, proper semantic markup is required here, such as paragraph tags. Don't omit paragraph tags!

    \

    Also note the same for actions below. You'll need to include the full link markup.

    \ ", actions="Open a Modal Dialog", level='warning' -) %} +) }} -{% module Alert('A Success Alert', +{{ Alert('A Success Alert', message="

    Congratulations! You did a thing.

    ", level='success' -) %} +) }} -{% module Alert('An Error Alert', +{{ Alert('An Error Alert', message="

    Booooo. You're the worst.

    ", level='error' -) %} +) }} -{% module Alert('An Info Alert', +{{ Alert('An Info Alert', message="

    The more you know.

    " -) %} +) }}
    @@ -214,7 +216,7 @@
    - Inline Checkboxes {% module Icon('alert') %} + Inline Checkboxes {{ Icon('alert') }} @@ -234,7 +236,7 @@
    - Problem Radio Buttons {% module Icon('alert') %} + Problem Radio Buttons {{ Icon('alert') }} @@ -279,30 +281,30 @@
    Icons
    - {% module Icon('trash') %} 'trash'    - {% module Icon('document') %} 'document'    - {% module Icon('cloud') %} 'cloud'    - {% module Icon('chart') %} 'chart'    - {% module Icon('caret_up') %} 'caret_up'    - {% module Icon('caret_down') %} 'caret_down'    - {% module Icon('caret_right') %} 'caret_right'    - {% module Icon('caret_left') %} 'caret_left'    - {% module Icon('x') %} 'x'    - {% module Icon('search') %} 'search'    - {% module Icon('avatar') %} 'avatar'    - {% module Icon('download') %} 'download'    - {% module Icon('briefcase') %} 'briefcase'    - {% module Icon('bell') %} 'bell'    - {% module Icon('folder') %} 'folder'    - {% module Icon('help') %} 'help'    - {% module Icon('shield') %} 'shield'    - {% module Icon('info') %} 'info'    - {% module Icon('alert') %} 'alert'    - {% module Icon('link') %} 'link'    - {% module Icon('ok') %} 'ok'    - {% module Icon('checkmark') %} 'checkmark'    - {% module Icon('arrow-right') %} 'arrow-right'    - {% module Icon('arrow-down') %} 'arrow-down'    + {{ Icon('trash') }} 'trash'    + {{ Icon('document') }} 'document'    + {{ Icon('cloud') }} 'cloud'    + {{ Icon('chart') }} 'chart'    + {{ Icon('caret_up') }} 'caret_up'    + {{ Icon('caret_down') }} 'caret_down'    + {{ Icon('caret_right') }} 'caret_right'    + {{ Icon('caret_left') }} 'caret_left'    + {{ Icon('x') }} 'x'    + {{ Icon('search') }} 'search'    + {{ Icon('avatar') }} 'avatar'    + {{ Icon('download') }} 'download'    + {{ Icon('briefcase') }} 'briefcase'    + {{ Icon('bell') }} 'bell'    + {{ Icon('folder') }} 'folder'    + {{ Icon('help') }} 'help'    + {{ Icon('shield') }} 'shield'    + {{ Icon('info') }} 'info'    + {{ Icon('alert') }} 'alert'    + {{ Icon('link') }} 'link'    + {{ Icon('ok') }} 'ok'    + {{ Icon('checkmark') }} 'checkmark'    + {{ Icon('arrow-right') }} 'arrow-right'    + {{ Icon('arrow-down') }} 'arrow-down'   
    @@ -360,4 +362,4 @@ Action group link
    -{% end %} +{% endblock %} From a9d13907044f509981b8d076e264d6a354668840 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 2 Aug 2018 13:44:01 -0400 Subject: [PATCH 086/173] Rename assets environment to play nicely with script/setup --- atst/app.py | 4 ++-- atst/assets.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atst/app.py b/atst/app.py index cd54f15d..46b017bb 100644 --- a/atst/app.py +++ b/atst/app.py @@ -5,7 +5,7 @@ from flask import Flask, request, g from unipath import Path from atst.database import db -from atst.assets import assets +from atst.assets import environment as assets_environment from atst.routes import bp from atst.routes.workspaces import bp as workspace_routes @@ -29,7 +29,7 @@ def make_app(config): make_flask_callbacks(app) db.init_app(app) - assets.init_app(app) + assets_environment.init_app(app) app.register_blueprint(bp) app.register_blueprint(workspace_routes) diff --git a/atst/assets.py b/atst/assets.py index bed898ac..aef6b35e 100644 --- a/atst/assets.py +++ b/atst/assets.py @@ -1,7 +1,7 @@ from flask_assets import Environment, Bundle from atst.home import home -assets = Environment() +environment = Environment() css = Bundle( "../scss/atat.scss", @@ -10,4 +10,4 @@ css = Bundle( depends=("**/*.scss"), ) -assets.register("css", css) +environment.register("css", css) From 3ddc76c3307ab49ba1c2f38548f1154cea03aae2 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 2 Aug 2018 13:44:54 -0400 Subject: [PATCH 087/173] Formatting --- atst/routes/requests/financial_verification.py | 5 ++++- atst/routes/requests/requests_form.py | 9 ++++++--- atst/routes/workspaces.py | 11 +++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/atst/routes/requests/financial_verification.py b/atst/routes/requests/financial_verification.py index e0d08a37..4471b524 100644 --- a/atst/routes/requests/financial_verification.py +++ b/atst/routes/requests/financial_verification.py @@ -4,6 +4,7 @@ from . import requests_bp from atst.domain.requests import Requests from atst.forms.financial import FinancialForm + @requests_bp.route("/requests/verify/", methods=["GET"]) def financial_verification(request_id=None): request = Requests.get(request_id) @@ -30,7 +31,9 @@ def update_financial_verification(request_id): if valid: redirect(url_for("requests.financial_verification_submitted")) else: - return render_template("requests/financial_verification.html", **rerender_args) + return render_template( + "requests/financial_verification.html", **rerender_args + ) else: return render_template("requests/financial_verification.html", **rerender_args) diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index 4e9b5018..cd12fbcd 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -21,7 +21,9 @@ def requests_form_new(screen): ) -@requests_bp.route("/requests/new/", methods=["GET"], defaults={"request_id": None}) +@requests_bp.route( + "/requests/new/", methods=["GET"], defaults={"request_id": None} +) @requests_bp.route("/requests/new//", methods=["GET"]) def requests_form_update(screen=1, request_id=None): request = Requests.get(request_id) if request_id is not None else None @@ -39,7 +41,9 @@ def requests_form_update(screen=1, request_id=None): ) -@requests_bp.route("/requests/new/", methods=["POST"], defaults={"request_id": None}) +@requests_bp.route( + "/requests/new/", methods=["POST"], defaults={"request_id": None} +) @requests_bp.route("/requests/new//", methods=["POST"]) def requests_update(screen=1, request_id=None): screen = int(screen) @@ -84,7 +88,6 @@ def requests_update(screen=1, request_id=None): return render_template("requests/screen-%d.html" % int(screen), **rerender_args) - @requests_bp.route("/requests/submit/", methods=["POST"]) def requests_submit(request_id=None): request = Requests.get(request_id) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index 1f3b47f2..43b3b050 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -14,18 +14,25 @@ mock_workspaces = [ } ] + @bp.route("/workspaces") def workspaces(): return render_template("workspaces.html", page=5, workspaces=mock_workspaces) + @bp.route("/workspaces//projects") def workspace_projects(workspace_id): projects_repo = Projects() projects = projects_repo.get_many(workspace_id) - return render_template("workspace_projects.html", workspace_id=workspace_id, projects=projects) + return render_template( + "workspace_projects.html", workspace_id=workspace_id, projects=projects + ) + @bp.route("/workspaces//members") def workspace_members(workspace_id): members_repo = Members() members = members_repo.get_many(workspace_id) - return render_template("workspace_members.html", workspace_id=workspace_id, members=members) + return render_template( + "workspace_members.html", workspace_id=workspace_id, members=members + ) From 89bde5fb2cd22f3c6f2da4c18ce4a8f36c317987 Mon Sep 17 00:00:00 2001 From: Luis Cielak Date: Mon, 30 Jul 2018 17:26:07 -0400 Subject: [PATCH 088/173] Add member placeholder info --- templates/member_edit.html.to | 73 ++++++++----------- .../navigation/workspace_navigation.html.to | 32 ++++---- templates/workspace_members.html | 16 ++-- 3 files changed, 51 insertions(+), 70 deletions(-) diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 24893bf2..d454152c 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -16,40 +16,39 @@ level="info" ) %} -
    -
    -

    {{ member_name }}

    -
    Workspace Role
    {{member_workspace_role}}
    -
    -
    -
    -
    -
    DOD ID:
    -
    {{ member_id }}
    -
    -
    -
    Email:
    -
    {{ member_email }}
    -
    -
    - edit account details + +
    +
    +

    + {% if is_new_member %} + Add new member + {% else %} + {{ member_name }} + {% end %} +

    +
    Workspace Role {{member_workspace_role}}
    -
    {%- endmacro %} - -{% macro TextInput(field, placeholder='') -%} -
    - - - {{ field(placeholder=placeholder) | safe }} - - {% if field.errors %} - {% for error in field.errors %} - {{ error }} - {% endfor %} - {% endif %} -
    -{%- endmacro %} - -{% macro OptionsInput(field, inline=False) -%} -
    - -
    - - {{ field.label }} - - {% if field.description %} - {{ field.description | safe }} - {% endif %} - - {% if field.errors %} - {{ Icon('alert') }} - {% endif %} - - - {{ field() }} - - {% if field.errors %} - {% for error in field.errors %} - {{ error }} - {% endfor %} - {% endif %} - -
    -
    - -{%- endmacro %} From cd2f17e0849123827aebdd0a740209c9142a9e14 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 2 Aug 2018 10:47:31 -0400 Subject: [PATCH 091/173] Update alembic/env to work with flask app --- alembic/env.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/alembic/env.py b/alembic/env.py index 6a9d9749..91b96364 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -30,11 +30,10 @@ sys.path.append(parent_dir) from atst.app import make_config app_config = make_config() -config.set_main_option('sqlalchemy.url', app_config['default']['DATABASE_URI']) +config.set_main_option('sqlalchemy.url', app_config['DATABASE_URI']) -from atst.database import make_db +from atst.database import db from atst.models import * -db = make_db(app_config) target_metadata = Base.metadata From ccf4108665afeea7083271ae13e6c110d0c3c6e4 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 2 Aug 2018 10:51:12 -0400 Subject: [PATCH 092/173] Add parcel/vue js deps --- package.json | 4 +- yarn.lock | 6585 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 6588 insertions(+), 1 deletion(-) create mode 100644 yarn.lock diff --git a/package.json b/package.json index 5e9a5920..9a474e0d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "license": "MIT", "dependencies": { "npm": "^6.0.1", - "uswds": "^1.6.3" + "parcel": "^1.9.7", + "uswds": "^1.6.3", + "vue": "^2.5.17" } } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..ca8a5e51 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6585 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" + +"@types/node@^8.5.5": + version "8.10.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.23.tgz#e5ccfdafff42af5397c29669b6d7d65f7d629a00" + +JSONStream@^1.0.3, JSONStream@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.3.tgz#27b4b8fbbfeab4e71bcf551e7f27be8d952239bf" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1, abbrev@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" + dependencies: + acorn "^5.0.0" + +acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.5.2.tgz#2ca723df19d997b05824b69f6c7fb091fc42c322" + dependencies: + acorn "^5.7.1" + acorn-dynamic-import "^3.0.0" + xtend "^4.0.1" + +acorn@^5.0.0, acorn@^5.2.1, acorn@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + +agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.4.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.1.tgz#4eba75cf2ad258fc09efd506cdb8d8c2971d35a4" + dependencies: + humanize-ms "^1.2.1" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +ansi-to-html@^0.6.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.6.tgz#58a8d04b87ec9a85e3ad273c12a5fbc7147b9c42" + dependencies: + entities "^1.1.1" + +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + +ansistyles@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2, aproba@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +"aproba@^1.1.2 || 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-foreach@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-foreach/-/array-foreach-1.0.2.tgz#cd36e42f0f482108c406b35c3612a8970b2fccea" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.1.1, assert@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.25.0, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.25.0, babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.26.0: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.15.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon-walk@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" + dependencies: + babel-runtime "^6.11.6" + babel-types "^6.15.0" + lodash.clone "^4.5.0" + +babylon@^6.17.4, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +bin-links@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" + dependencies: + bluebird "^3.5.0" + cmd-shim "^2.0.2" + gentle-fs "^2.0.0" + graceful-fs "^4.1.11" + write-file-atomic "^2.3.0" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +bindings@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.0.5, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@~3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boxen@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +brfs@^1.2.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" + dependencies: + quote-stream "^1.0.1" + resolve "^1.1.5" + static-module "^2.2.0" + through2 "^2.0.0" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + +browser-pack@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.8.0" + defined "^1.0.0" + safe-buffer "^5.1.1" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^1.11.0, browser-resolve@^1.7.0: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + dependencies: + resolve "1.1.7" + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + dependencies: + pako "~1.0.5" + +browserify-zlib@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +browserify@^13.0.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-13.3.0.tgz#b5a9c9020243f0c70e4675bec8223bc627e415ce" + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.1.2" + buffer "^4.1.0" + cached-path-relative "^1.0.0" + concat-stream "~1.5.1" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "~1.1.0" + duplexer2 "~0.1.2" + events "~1.1.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "~0.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + module-deps "^4.0.8" + os-browserify "~0.1.1" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "~0.10.0" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "~0.0.0" + url "~0.11.0" + util "~0.10.1" + vm-browserify "~0.0.1" + xtend "^4.0.0" + +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.0.1.tgz#61c05ce2a5843c7d96166408bc23d58b5416e818" + dependencies: + caniuse-lite "^1.0.30000865" + electron-to-chromium "^1.3.52" + node-releases "^1.0.0-alpha.10" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + +buffer@^4.1.0, buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + +byte-size@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.3.tgz#b7c095efc68eadf82985fccd9a2df43a74fa2ccd" + +cacache@^10.0.4: + version "10.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" + dependencies: + bluebird "^3.5.1" + chownr "^1.0.1" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.1" + mississippi "^2.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^5.2.4" + unique-filename "^1.1.0" + y18n "^4.0.0" + +cacache@^11.0.1, cacache@^11.0.2, cacache@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.1.0.tgz#3d76dbc2e9da413acaad2557051960a4dad3e1a4" + dependencies: + bluebird "^3.5.1" + chownr "^1.0.1" + figgy-pudding "^3.1.0" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.3" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^6.0.0" + unique-filename "^1.1.0" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cached-path-relative@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" + +call-limit@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30000872" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000872.tgz#3f6e53b63d373768bf99e896133d66ef89c49999" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000865: + version "1.0.30000865" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz#70026616e8afe6e1442f8bb4e1092987d81a2f25" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + lodash.debounce "^4.0.8" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.5" + optionalDependencies: + fsevents "^1.2.2" + +chownr@^1.0.1, chownr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +ci-info@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" + +cidr-regex@^2.0.8: + version "2.0.9" + resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.9.tgz#9c17bb2b18e15af07f7d0c3b994b961d687ed1c9" + dependencies: + ip-regex "^2.1.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + dependencies: + chalk "^1.1.3" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classlist-polyfill@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz#935bc2dfd9458a876b279617514638bcaa964a2e" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + +cli-columns@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" + dependencies: + string-width "^2.0.0" + strip-ansi "^3.0.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + +clones@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/clones/-/clones-1.1.0.tgz#87e904132d6140c5c0b72006c08c0d05bd7b63b3" + +cmd-shim@^2.0.2, cmd-shim@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" + dependencies: + graceful-fs "^4.1.2" + mkdirp "~0.5.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + dependencies: + q "^1.1.2" + +coa@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" + dependencies: + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +color-name@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + dependencies: + color-name "^1.0.0" + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + dependencies: + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" + +color@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + dependencies: + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@^1.1.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.1.tgz#4accdb89cf2cabc7f982771925e9468784f32f3d" + +colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +columnify@~1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + +combine-source-map@^0.8.0, combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.7.tgz#16828f0c3ff2b0c58805861ef211b64fc15692a8" + +commander@^2.11.0, commander@^2.9.0, commander@~2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + +commander@~2.14.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.1, concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concat-stream@~1.5.0, concat-stream@~1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" + dependencies: + inherits "~2.0.1" + readable-stream "~2.0.0" + typedarray "~0.0.5" + +config-chain@~1.1.11, config-chain@~1.1.5: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +constants-browserify@^1.0.0, constants-browserify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cosmiconfig@^5.0.0: + version "5.0.5" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.5.tgz#a809e3c2306891ce17ab70359dc8bdf661fe2cd0" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.4: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + +css-declaration-sorter@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-3.0.1.tgz#d0e3056b0fd88dc1ea9dceff435adbe9c702a7f8" + dependencies: + postcss "^6.0.0" + timsort "^0.3.0" + +css-select-base-adapter@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz#0102b3d14630df86c3eb9fa9f5456270106cf990" + +css-select@~1.3.0-rc0: + version "1.3.0-rc0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.3.0-rc0.tgz#6f93196aaae737666ea1036a8cb14a8fcb7a9231" + dependencies: + boolbase "^1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "^1.0.1" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha25: + version "1.0.0-alpha25" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha25.tgz#1bbfabfbf6eeef4f01d9108ff2edd0be2fe35597" + dependencies: + mdn-data "^1.0.0" + source-map "^0.5.3" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + +css-url-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + +cssnano-preset-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.0.tgz#c334287b4f7d49fb2d170a92f9214655788e3b6b" + dependencies: + css-declaration-sorter "^3.0.0" + cssnano-util-raw-cache "^4.0.0" + postcss "^6.0.0" + postcss-calc "^6.0.0" + postcss-colormin "^4.0.0" + postcss-convert-values "^4.0.0" + postcss-discard-comments "^4.0.0" + postcss-discard-duplicates "^4.0.0" + postcss-discard-empty "^4.0.0" + postcss-discard-overridden "^4.0.0" + postcss-merge-longhand "^4.0.0" + postcss-merge-rules "^4.0.0" + postcss-minify-font-values "^4.0.0" + postcss-minify-gradients "^4.0.0" + postcss-minify-params "^4.0.0" + postcss-minify-selectors "^4.0.0" + postcss-normalize-charset "^4.0.0" + postcss-normalize-display-values "^4.0.0" + postcss-normalize-positions "^4.0.0" + postcss-normalize-repeat-style "^4.0.0" + postcss-normalize-string "^4.0.0" + postcss-normalize-timing-functions "^4.0.0" + postcss-normalize-unicode "^4.0.0" + postcss-normalize-url "^4.0.0" + postcss-normalize-whitespace "^4.0.0" + postcss-ordered-values "^4.0.0" + postcss-reduce-initial "^4.0.0" + postcss-reduce-transforms "^4.0.0" + postcss-svgo "^4.0.0" + postcss-unique-selectors "^4.0.0" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + +cssnano-util-raw-cache@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.0.tgz#be0a2856e25f185f5f7a2bcc0624e28b7f179a9f" + dependencies: + postcss "^6.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.0.tgz#d2a3de1039aa98bc4ec25001fa050330c2a16dac" + +cssnano@^3.4.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +cssnano@^4.0.0: + version "4.0.5" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.0.5.tgz#8789b5fdbe7be05d8a0f7e45c4c789ebe712f5aa" + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.0" + is-resolvable "^1.0.0" + postcss "^6.0.0" + +csso@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + dependencies: + css-tree "1.0.0-alpha.29" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +deasync@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.13.tgz#815c2b69bbd1117cae570152cd895661c09f20ea" + dependencies: + bindings "~1.2.1" + nan "^2.0.7" + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debuglog@*, debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + +decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +deps-sort@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" + dependencies: + JSONStream "^1.0.3" + shasum "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-indent@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + +detective@^4.0.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +dezalgo@^1.0.0, dezalgo@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + dependencies: + asap "^2.0.0" + wrappy "1" + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + +domain-browser@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + dependencies: + domelementtype "1" + +domready@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/domready/-/domready-1.0.8.tgz#91f252e597b65af77e745ae24dd0185d5e26d58c" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.0, dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + +dotenv@^5.0.0, dotenv@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + dependencies: + readable-stream "^2.0.2" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +editor@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" + +editorconfig@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" + dependencies: + bluebird "^3.0.5" + commander "^2.9.0" + lru-cache "^3.2.0" + semver "^5.1.0" + sigmund "^1.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.52: + version "1.3.55" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.55.tgz#f150e10b20b77d9d41afcca312efe0c3b1a7fdce" + +elem-dataset@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/elem-dataset/-/elem-dataset-1.1.1.tgz#18f07fa7fc71ebd49b0f9f63819cb03c8276577a" + +element-closest@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/element-closest/-/element-closest-2.0.2.tgz#72a740a107453382e28df9ce5dbb5a8df0f966ec" + +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + +errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.5.1, es-abstract@^1.6.1: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es6-promise@^4.0.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + dependencies: + es6-promise "^4.0.3" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@^1.8.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@~1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + +estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +events@^1.0.0, events@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.0, extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +falafel@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" + dependencies: + acorn "^5.0.0" + foreach "^2.0.5" + isarray "0.0.1" + object-keys "^1.0.6" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.0.1" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.1" + micromatch "^3.1.10" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figgy-pudding@^3.0.0, figgy-pudding@^3.1.0, figgy-pudding@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.2.0.tgz#464626b73d7b0fc045a99753d191b0785957ff73" + +filesize@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-npm-prefix@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + +flush-write-stream@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.4" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +from2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" + dependencies: + inherits "~2.0.1" + readable-stream "~1.1.10" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" + dependencies: + graceful-fs "^4.1.2" + path-is-inside "^1.0.1" + rimraf "^2.5.2" + +fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +fstream@^1.0.0, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +fswatcher-child@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fswatcher-child/-/fswatcher-child-1.0.5.tgz#134d012ffa74918975617e00e56e4139f36cb140" + dependencies: + chokidar "^2.0.3" + +function-bind@^1.1.0, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +genfun@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" + +gentle-fs@^2.0.0, gentle-fs@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.0.1.tgz#585cfd612bfc5cd52471fdb42537f016a5ce3687" + dependencies: + aproba "^1.1.2" + fs-vacuum "^1.2.10" + graceful-fs "^4.1.11" + iferr "^0.1.5" + mkdirp "^0.5.1" + path-is-inside "^1.0.2" + read-cmd-shim "^1.0.1" + slide "^1.1.6" + +get-assigned-identifiers@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + +get-port@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@~4.1.11: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +grapheme-breaker@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" + dependencies: + brfs "^1.2.0" + unicode-trie "^0.3.1" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-unicode@^2.0.0, has-unicode@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + +html-comment-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" + +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" + +htmlnano@^0.1.9: + version "0.1.9" + resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.1.9.tgz#e6137aea84d20311a3875c42eb2799a1ff352627" + dependencies: + cssnano "^3.4.0" + object-assign "^4.0.1" + posthtml "^0.11.3" + posthtml-render "^1.1.3" + svgo "^1.0.5" + uglify-es "^3.3.9" + +htmlparser2@^3.9.2: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +http-cache-semantics@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + dependencies: + agent-base "4" + debug "3.1.0" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + +https-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" + +https-proxy-agent@^2.2.0, https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + dependencies: + ms "^2.0.0" + +iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + +iferr@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.2.tgz#e9fde49a9da06dc4a4194c6c9ed6d08305037a6d" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + +imurmurhash@*, imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4, inflight@~1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +init-package-json@^1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" + dependencies: + source-map "~0.5.3" + +insert-module-globals@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" + dependencies: + JSONStream "^1.0.3" + acorn-node "^1.5.2" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" + is-buffer "^1.1.0" + path-is-absolute "^1.0.1" + process "~0.11.0" + through2 "^2.0.0" + undeclared-identifiers "^1.1.2" + xtend "^4.0.0" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + +ip@^1.1.4, ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.0, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + +is-ci@^1.0.10: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" + dependencies: + ci-info "^1.0.0" + +is-cidr@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-2.0.6.tgz#4b01c9693d8e18399dacd18a4f3d60ea5871ac60" + dependencies: + cidr-regex "^2.0.8" + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + dependencies: + html-comment-regex "^1.1.0" + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-url@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isarray@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0, isobject@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-base64@^2.1.9: + version "2.4.8" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" + +js-beautify@^1.7.5: + version "1.7.5" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.7.5.tgz#69d9651ef60dbb649f65527b53674950138a7919" + dependencies: + config-chain "~1.1.5" + editorconfig "^0.13.2" + mkdirp "~0.5.0" + nopt "~3.0.1" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.10.0, js-yaml@^3.9.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + dependencies: + minimist "^1.2.0" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keyboardevent-key-polyfill@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keyboardevent-key-polyfill/-/keyboardevent-key-polyfill-1.1.0.tgz#8a319d8e45a13172fca56286372f90c1d4c7014c" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +labeled-stream-splicer@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" + dependencies: + inherits "^2.0.1" + isarray "^2.0.4" + stream-splicer "^2.0.0" + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + dependencies: + package-json "^4.0.0" + +lazy-property@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +libcipm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-2.0.1.tgz#2f4ebf8562e0fc6e46f415373674e4cf3ac4b9ba" + dependencies: + bin-links "^1.1.2" + bluebird "^3.5.1" + find-npm-prefix "^1.0.2" + graceful-fs "^4.1.11" + lock-verify "^2.0.2" + mkdirp "^0.5.1" + npm-lifecycle "^2.0.3" + npm-logical-tree "^1.2.1" + npm-package-arg "^6.1.0" + pacote "^8.1.6" + protoduck "^5.0.0" + read-package-json "^2.0.13" + rimraf "^2.6.2" + worker-farm "^1.6.0" + +libnpmhook@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-4.0.1.tgz#63641654de772cbeb96a88527a7fd5456ec3c2d7" + dependencies: + figgy-pudding "^3.1.0" + npm-registry-fetch "^3.0.0" + +libnpx@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.0.tgz#1bf4a1c9f36081f64935eb014041da10855e3102" + dependencies: + dotenv "^5.0.1" + npm-package-arg "^6.0.0" + rimraf "^2.6.2" + safe-buffer "^5.1.0" + update-notifier "^2.3.0" + which "^1.3.0" + y18n "^4.0.0" + yargs "^11.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lock-verify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.0.2.tgz#148e4f85974915c9e3c34d694b7de9ecb18ee7a8" + dependencies: + npm-package-arg "^5.1.2 || 6" + semver "^5.4.1" + +lockfile@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" + dependencies: + signal-exit "^3.0.2" + +lodash._baseindexof@*: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._bindcallback@*: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" + +lodash._cacheindexof@*: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" + +lodash._createcache@*: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" + dependencies: + lodash._getnative "^3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + +lodash._getnative@*, lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash.clone@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" + +lodash.clonedeep@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + +lodash.debounce@^4.0.7, lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" + +lodash.restparam@*: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash.union@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + +lodash.uniq@^4.5.0, lodash.uniq@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + +lodash.without@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" + +lodash@^4.17.4: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + dependencies: + chalk "^2.0.1" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + dependencies: + pseudomap "^1.0.1" + +lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + dependencies: + vlq "^0.2.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + dependencies: + pify "^3.0.0" + +"make-fetch-happen@^2.5.0 || 3 || 4", make-fetch-happen@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" + dependencies: + agentkeepalive "^3.4.1" + cacache "^11.0.1" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + lru-cache "^4.1.2" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^4.0.0" + ssri "^6.0.0" + +make-fetch-happen@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-3.0.0.tgz#7b661d2372fc4710ab5cc8e1fa3c290eea69a961" + dependencies: + agentkeepalive "^3.4.1" + cacache "^10.0.4" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.0" + lru-cache "^4.1.2" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^3.0.1" + ssri "^5.2.4" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +matches-selector@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/matches-selector/-/matches-selector-1.2.0.tgz#d1814e7e8f43e69d22ac33c9af727dc884ecf12a" + +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" + +md5.js@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +mdn-data@^1.0.0, mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + +meant@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + dependencies: + source-map "^0.5.6" + +merge2@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mississippi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^2.0.1" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +module-deps@^4.0.8: + version "4.1.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" + concat-stream "~1.5.0" + defined "^1.0.0" + detective "^4.0.0" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.1.3" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +ms@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +mute-stream@~0.0.4: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +nan@^2.0.7, nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +nice-try@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" + +node-fetch-npm@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + +node-forge@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" + +node-gyp@^3.6.2, node-gyp@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.7.0.tgz#789478e8f6c45e277aa014f3e28f958f286f9203" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request ">=2.9.0 <2.82.0" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + +node-libs-browser@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.0" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.0.0-alpha.10: + version "1.0.0-alpha.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.10.tgz#61c8d5f9b5b2e05d84eba941d05b6f5202f68a2a" + dependencies: + semver "^5.3.0" + +"nopt@2 || 3", nopt@~3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + +normalize-url@^1.4.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.2.0.tgz#98d0948afc82829f374320f405fe9ca55a5f8567" + +npm-audit-report@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.3.1.tgz#e79ea1fcb5ffaf3031102b389d5222c2b0459632" + dependencies: + cli-table3 "^0.5.0" + console-control-strings "^1.1.0" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-cache-filename@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" + +npm-install-checks@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7" + dependencies: + semver "^2.3.0 || 3.x || 4 || 5" + +npm-lifecycle@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.0.3.tgz#696bedf1143371163e9cc16fe872357e25d8d90e" + dependencies: + byline "^5.0.0" + graceful-fs "^4.1.11" + node-gyp "^3.6.2" + resolve-from "^4.0.0" + slide "^1.1.6" + uid-number "0.0.6" + umask "^1.1.0" + which "^1.3.0" + +npm-logical-tree@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" + +"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", "npm-package-arg@^5.1.2 || 6", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" + dependencies: + hosted-git-info "^2.6.0" + osenv "^0.1.5" + semver "^5.5.0" + validate-npm-package-name "^3.0.0" + +npm-packlist@^1.1.10, npm-packlist@^1.1.6, npm-packlist@~1.1.10: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-pick-manifest@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.1.0.tgz#dc381bdd670c35d81655e1d5a94aa3dd4d87fce5" + dependencies: + npm-package-arg "^6.0.0" + semver "^5.4.1" + +npm-profile@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-3.0.2.tgz#58d568f1b56ef769602fd0aed8c43fa0e0de0f57" + dependencies: + aproba "^1.1.2 || 2" + make-fetch-happen "^2.5.0 || 3 || 4" + +npm-registry-client@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.6.0.tgz#7f1529f91450732e89f8518e0f21459deea3e4c4" + dependencies: + concat-stream "^1.5.2" + graceful-fs "^4.1.6" + normalize-package-data "~1.0.1 || ^2.0.0" + npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + once "^1.3.3" + request "^2.74.0" + retry "^0.10.0" + safe-buffer "^5.1.1" + semver "2 >=2.2.1 || 3.x || 4 || 5" + slide "^1.1.3" + ssri "^5.2.4" + optionalDependencies: + npmlog "2 || ^3.1.0 || ^4.0.0" + +npm-registry-fetch@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-1.1.1.tgz#710bc5947d9ee2c549375072dab6d5d17baf2eb2" + dependencies: + bluebird "^3.5.1" + figgy-pudding "^3.0.0" + lru-cache "^4.1.2" + make-fetch-happen "^3.0.0" + npm-package-arg "^6.0.0" + safe-buffer "^5.1.1" + +npm-registry-fetch@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.2.0.tgz#94ec859c4dd395f924e575cee471da6fd3906d53" + dependencies: + bluebird "^3.5.1" + figgy-pudding "^3.2.0" + lru-cache "^4.1.3" + make-fetch-happen "^4.0.1" + npm-package-arg "^6.1.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npm-user-validate@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" + +npm@^6.0.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.3.0.tgz#de7df51f6d1b05b088486097cf7993dbbcac752f" + dependencies: + JSONStream "^1.3.3" + abbrev "~1.1.1" + ansicolors "~0.3.2" + ansistyles "~0.1.3" + aproba "~1.2.0" + archy "~1.0.0" + bin-links "^1.1.2" + bluebird "~3.5.1" + byte-size "^4.0.3" + cacache "^11.1.0" + call-limit "~1.1.0" + chownr "~1.0.1" + cli-columns "^3.1.2" + cli-table3 "^0.5.0" + cmd-shim "~2.0.2" + columnify "~1.5.4" + config-chain "~1.1.11" + detect-indent "~5.0.0" + detect-newline "^2.1.0" + dezalgo "~1.0.3" + editor "~1.0.0" + figgy-pudding "^3.2.0" + find-npm-prefix "^1.0.2" + fs-vacuum "~1.2.10" + fs-write-stream-atomic "~1.0.10" + gentle-fs "^2.0.1" + glob "~7.1.2" + graceful-fs "~4.1.11" + has-unicode "~2.0.1" + hosted-git-info "^2.6.0" + iferr "^1.0.0" + inflight "~1.0.6" + inherits "~2.0.3" + ini "^1.3.5" + init-package-json "^1.10.3" + is-cidr "^2.0.6" + json-parse-better-errors "^1.0.2" + lazy-property "~1.0.0" + libcipm "^2.0.0" + libnpmhook "^4.0.1" + libnpx "^10.2.0" + lock-verify "^2.0.2" + lockfile "^1.0.4" + lodash._baseuniq "~4.6.0" + lodash.clonedeep "~4.5.0" + lodash.union "~4.6.0" + lodash.uniq "~4.5.0" + lodash.without "~4.4.0" + lru-cache "^4.1.3" + meant "~1.0.1" + mississippi "^3.0.0" + mkdirp "~0.5.1" + move-concurrently "^1.0.1" + node-gyp "^3.7.0" + nopt "~4.0.1" + normalize-package-data "~2.4.0" + npm-audit-report "^1.3.1" + npm-cache-filename "~1.0.2" + npm-install-checks "~3.0.0" + npm-lifecycle "^2.0.3" + npm-package-arg "^6.1.0" + npm-packlist "~1.1.10" + npm-pick-manifest "^2.1.0" + npm-profile "^3.0.2" + npm-registry-client "^8.5.1" + npm-registry-fetch "^1.1.0" + npm-user-validate "~1.0.0" + npmlog "~4.1.2" + once "~1.4.0" + opener "~1.4.3" + osenv "^0.1.5" + pacote "^8.1.6" + path-is-inside "~1.0.2" + promise-inflight "~1.0.1" + qrcode-terminal "^0.12.0" + query-string "^6.1.0" + qw "~1.0.1" + read "~1.0.7" + read-cmd-shim "~1.0.1" + read-installed "~4.0.3" + read-package-json "^2.0.13" + read-package-tree "^5.2.1" + readable-stream "^2.3.6" + request "^2.81.0" + retry "^0.12.0" + rimraf "~2.6.2" + safe-buffer "^5.1.2" + semver "^5.5.0" + sha "~2.0.1" + slide "~1.1.6" + sorted-object "~2.0.1" + sorted-union-stream "~2.1.3" + ssri "^6.0.0" + stringify-package "^1.0.0" + tar "^4.4.4" + text-table "~0.2.0" + tiny-relative-date "^1.3.0" + uid-number "0.0.6" + umask "~1.1.0" + unique-filename "~1.1.0" + unpipe "~1.0.0" + update-notifier "^2.5.0" + uuid "^3.3.2" + validate-npm-package-license "^3.0.3" + validate-npm-package-name "~3.0.0" + which "^1.3.1" + worker-farm "^1.6.0" + write-file-atomic "^2.3.0" + +"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.2, npmlog@~4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" + +object-keys@^1.0.6, object-keys@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +object.values@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opener@~1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" + +opn@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" + dependencies: + is-wsl "^1.1.0" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +ora@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" + dependencies: + chalk "^2.3.1" + cli-cursor "^2.1.0" + cli-spinners "^1.1.0" + log-symbols "^2.2.0" + strip-ansi "^4.0.0" + wcwidth "^1.0.1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + +os-browserify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@0, osenv@^0.1.4, osenv@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +pacote@^8.1.6: + version "8.1.6" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-8.1.6.tgz#8e647564d38156367e7a9dc47a79ca1ab278d46e" + dependencies: + bluebird "^3.5.1" + cacache "^11.0.2" + get-stream "^3.0.0" + glob "^7.1.2" + lru-cache "^4.1.3" + make-fetch-happen "^4.0.1" + minimatch "^3.0.4" + minipass "^2.3.3" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.1.10" + npm-pick-manifest "^2.1.0" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.0" + rimraf "^2.6.2" + safe-buffer "^5.1.2" + semver "^5.5.0" + ssri "^6.0.0" + tar "^4.4.3" + unique-filename "^1.1.0" + which "^1.3.0" + +pako@^0.2.5, pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parcel@^1.9.7: + version "1.9.7" + resolved "https://registry.yarnpkg.com/parcel/-/parcel-1.9.7.tgz#77ca0cdb305d8e9365ded4762ee39ca760b0c219" + dependencies: + ansi-to-html "^0.6.4" + babel-code-frame "^6.26.0" + babel-core "^6.25.0" + babel-generator "^6.25.0" + babel-plugin-transform-es2015-modules-commonjs "^6.26.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-preset-env "^1.7.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.17.4" + babylon-walk "^1.0.2" + browserslist "^3.2.6" + chalk "^2.1.0" + clone "^2.1.1" + command-exists "^1.2.6" + commander "^2.11.0" + cross-spawn "^6.0.4" + cssnano "^4.0.0" + deasync "^0.1.13" + dotenv "^5.0.0" + fast-glob "^2.2.2" + filesize "^3.6.0" + fswatcher-child "^1.0.3" + get-port "^3.2.0" + grapheme-breaker "^0.3.2" + htmlnano "^0.1.9" + is-glob "^4.0.0" + is-url "^1.2.2" + js-yaml "^3.10.0" + json5 "^1.0.1" + micromatch "^3.0.4" + mkdirp "^0.5.1" + node-forge "^0.7.1" + node-libs-browser "^2.0.0" + opn "^5.1.0" + ora "^2.1.0" + physical-cpu-count "^2.0.0" + postcss "^6.0.19" + postcss-value-parser "^3.3.0" + posthtml "^0.11.2" + posthtml-parser "^0.4.0" + posthtml-render "^1.1.3" + resolve "^1.4.0" + semver "^5.4.1" + serialize-to-js "^1.1.1" + serve-static "^1.12.4" + source-map "0.6.1" + strip-ansi "^4.0.0" + terser "^3.7.3" + toml "^2.3.3" + tomlify-j0.4 "^3.0.0" + v8-compile-cache "^2.0.0" + ws "^5.1.1" + +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + dependencies: + path-platform "~0.11.15" + +parse-asn1@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pbkdf2@^3.0.3: + version "3.0.16" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +physical-cpu-count@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + +postcss-calc@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.1.tgz#3d24171bbf6e7629d422a436ebfe6dd9511f4330" + dependencies: + css-unit-converter "^1.1.1" + postcss "^6.0.0" + postcss-selector-parser "^2.2.2" + reduce-css-calc "^2.0.0" + +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + +postcss-colormin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.1.tgz#6f1c18a0155bc69613f2ff13843e2e4ae8ff0bbe" + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + +postcss-convert-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.0.tgz#77d77d9aed1dc4e6956e651cc349d53305876f62" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + dependencies: + postcss "^5.0.14" + +postcss-discard-comments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.0.tgz#9684a299e76b3e93263ef8fd2adbf1a1c08fd88d" + dependencies: + postcss "^6.0.0" + +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + dependencies: + postcss "^5.0.4" + +postcss-discard-duplicates@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.0.tgz#42f3c267f85fa909e042c35767ecfd65cb2bd72c" + dependencies: + postcss "^6.0.0" + +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + dependencies: + postcss "^5.0.14" + +postcss-discard-empty@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.0.tgz#55e18a59c74128e38c7d2804bcfa4056611fb97f" + dependencies: + postcss "^6.0.0" + +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + dependencies: + postcss "^5.0.16" + +postcss-discard-overridden@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.0.tgz#4a0bf85978784cf1f81ed2c1c1fd9d964a1da1fa" + dependencies: + postcss "^6.0.0" + +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + +postcss-filter-plugins@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" + dependencies: + postcss "^5.0.4" + +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + dependencies: + postcss "^5.0.4" + +postcss-merge-longhand@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.4.tgz#bffc7c6ffa146591c993a0bb8373d65f9a06d4d0" + dependencies: + css-color-names "0.0.4" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + +postcss-merge-rules@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.1.tgz#430fd59b3f2ed2e8afcd0b31278eda39854abb10" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-minify-font-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.0.tgz#4cc33d283d6a81759036e757ef981d92cbd85bed" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + +postcss-minify-gradients@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.0.tgz#3fc3916439d27a9bb8066db7cdad801650eb090e" + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + +postcss-minify-params@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.0.tgz#05e9166ee48c05af651989ce84d39c1b4d790674" + dependencies: + alphanum-sort "^1.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-minify-selectors@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.0.tgz#b1e9f6c463416d3fcdcb26e7b785d95f61578aad" + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + dependencies: + postcss "^5.0.5" + +postcss-normalize-charset@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.0.tgz#24527292702d5e8129eafa3d1de49ed51a6ab730" + dependencies: + postcss "^6.0.0" + +postcss-normalize-display-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz#950e0c7be3445770a160fffd6b6644c3c0cd8f89" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.0.tgz#ee9343ab981b822c63ab72615ecccd08564445a3" + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.0.tgz#b711c592cf16faf9ff575e42fa100b6799083eff" + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.0.tgz#718cb6d30a6fac6ac6a830e32c06c07dbc66fe5d" + dependencies: + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.0.tgz#0351f29886aa981d43d91b2c2bd1aea6d0af6d23" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.0.tgz#5acd5d47baea5d17674b2ccc4ae5166fa88cdf97" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + +postcss-normalize-url@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.0.tgz#b7a9c8ad26cf26694c146eb2d68bd0cf49956f0d" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.0.tgz#1da7e76b10ae63c11827fa04fc3bb4a1efe99cc0" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + +postcss-ordered-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.0.0.tgz#58b40c74f72e022eb34152c12e4b0f9354482fc2" + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + dependencies: + postcss "^5.0.4" + +postcss-reduce-initial@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.1.tgz#f2d58f50cea2b0c5dc1278d6ea5ed0ff5829c293" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^6.0.0" + +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + +postcss-reduce-transforms@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.0.tgz#f645fc7440c35274f40de8104e14ad7163edf188" + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + +postcss-svgo@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.0.tgz#c0bbad02520fc636c9d78b0e8403e2e515c32285" + dependencies: + is-svg "^3.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss-unique-selectors@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.0.tgz#04c1e9764c75874261303402c41f0e9769fc5501" + dependencies: + alphanum-sort "^1.0.0" + postcss "^6.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.0, postcss@^6.0.19: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +posthtml-parser@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.3.3.tgz#3fe986fca9f00c0f109d731ba590b192f26e776d" + dependencies: + htmlparser2 "^3.9.2" + isobject "^2.1.0" + object-assign "^4.1.1" + +posthtml-parser@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.1.tgz#95b78fef766fbbe0a6f861b6e95582bc3d1ff933" + dependencies: + htmlparser2 "^3.9.2" + object-assign "^4.1.1" + +posthtml-render@^1.1.0, posthtml-render@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.4.tgz#95dac09892f4f183fad5ac823f08f42c0256551e" + +posthtml@^0.11.2, posthtml@^0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.3.tgz#17ea2921b0555b7455f33c977bd16d8b8cb74f27" + dependencies: + object-assign "^4.1.1" + posthtml-parser "^0.3.3" + posthtml-render "^1.1.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.0, prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@^0.11.10, process@~0.11.0: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +promise-inflight@^1.0.1, promise-inflight@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + +promzard@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" + dependencies: + read "1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + +protoduck@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.0.tgz#752145e6be0ad834cb25716f670a713c860dce70" + dependencies: + genfun "^4.0.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +pseudomap@^1.0.1, pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +public-encrypt@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + +pump@^2.0.0, pump@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +query-string@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.1.0.tgz#01e7d69f6a0940dac67a937d6c6325647aa4532a" + dependencies: + decode-uri-component "^0.2.0" + strict-uri-encode "^2.0.0" + +querystring-es3@^0.2.0, querystring-es3@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +quote-stream@^1.0.1, quote-stream@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" + dependencies: + buffer-equal "0.0.1" + minimist "^1.1.3" + through2 "^2.0.0" + +qw@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-cmd-shim@^1.0.1, read-cmd-shim@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" + dependencies: + graceful-fs "^4.1.2" + +read-installed@~4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" + dependencies: + readable-stream "^2.0.2" + +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" + dependencies: + glob "^7.1.1" + json-parse-better-errors "^1.0.1" + normalize-package-data "^2.0.0" + slash "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-tree@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + once "^1.3.0" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read@1, read@~1.0.1, read@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.1.10: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +receptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/receptor/-/receptor-1.0.0.tgz#bf54477e0387e44bebf3855120bbda5adea08f8b" + dependencies: + element-closest "^2.0.1" + keyboardevent-key-polyfill "^1.0.2" + matches-selector "^1.0.0" + object-assign "^4.1.0" + +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-css-calc@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.4.tgz#c20e9cda8445ad73d4ff4bea960c6f8353791708" + dependencies: + css-unit-converter "^1.1.1" + postcss-value-parser "^3.3.0" + +reduce-function-call@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" + dependencies: + balanced-match "^0.4.2" + +regenerate@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +registry-auth-token@^3.0.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +"request@>=2.9.0 <2.82.0": + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@^2.74.0, request@^2.81.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + +resolve-id-refs@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/resolve-id-refs/-/resolve-id-refs-0.1.0.tgz#3126624b887489da8fc0ae889632f8413ac6c3ec" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.4.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + +rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + dependencies: + aproba "^1.1.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +safer-eval@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.2.3.tgz#73ba74a34bc8a07d6a44135c815fd18a8eebe7a0" + dependencies: + clones "^1.1.0" + +sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serialize-to-js@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.1.tgz#2e87f61f938826d24c463a7cbd0dd2929ec38008" + dependencies: + js-beautify "^1.7.5" + safer-eval "^1.2.3" + +serve-static@^1.12.4: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" + dependencies: + graceful-fs "^4.1.2" + readable-stream "^2.0.2" + +shallow-copy@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + dependencies: + is-arrayish "^0.3.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slide@^1.1.3, slide@^1.1.6, slide@~1.1.3, slide@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +smart-buffer@^1.0.13: + version "1.1.15" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" + +smart-buffer@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +socks-proxy-agent@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" + dependencies: + agent-base "^4.1.0" + socks "^1.1.10" + +socks-proxy-agent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" + dependencies: + agent-base "~4.2.0" + socks "~2.2.0" + +socks@^1.1.10: + version "1.1.10" + resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" + dependencies: + ip "^1.1.4" + smart-buffer "^1.0.13" + +socks@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" + dependencies: + ip "^1.1.5" + smart-buffer "^4.0.1" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + dependencies: + is-plain-obj "^1.0.0" + +sorted-object@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" + +sorted-union-stream@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7" + dependencies: + from2 "^1.3.0" + stream-iterate "^1.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map-support@~0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +ssri@^5.2.4: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" + dependencies: + safe-buffer "^5.1.1" + +ssri@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.0.tgz#fc21bfc90e03275ac3e23d5a42e38b8a1cbc130d" + +stable@~0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + +static-eval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.0.tgz#0e821f8926847def7b4b50cda5d55c04a9b13864" + dependencies: + escodegen "^1.8.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +static-module@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" + dependencies: + concat-stream "~1.6.0" + convert-source-map "^1.5.1" + duplexer2 "~0.1.4" + escodegen "~1.9.0" + falafel "^2.1.0" + has "^1.0.1" + magic-string "^0.22.4" + merge-source-map "1.0.4" + object-inspect "~1.4.0" + quote-stream "~1.0.2" + readable-stream "~2.3.3" + shallow-copy "~0.0.1" + static-eval "^2.0.0" + through2 "~2.0.3" + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +stream-browserify@^2.0.0, stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.0.0, stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-iterate@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" + dependencies: + readable-stream "^2.1.5" + stream-shift "^1.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + +stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~0.10.0, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringify-package@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.0.tgz#e02828089333d7d45cd8c287c30aa9a13375081b" + +stringstream@~0.0.4: + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +stylehacks@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.0.tgz#64b323951c4a24e5fc7b2ec06c137bf32d155e8a" + dependencies: + browserslist "^4.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + dependencies: + minimist "^1.1.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + +svgo@^1.0.0, svgo@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.0.5.tgz#7040364c062a0538abacff4401cea6a26a7a389a" + dependencies: + coa "~2.0.1" + colors "~1.1.2" + css-select "~1.3.0-rc0" + css-select-base-adapter "~0.1.0" + css-tree "1.0.0-alpha25" + css-url-regex "^1.1.0" + csso "^3.5.0" + js-yaml "~3.10.0" + mkdirp "~0.5.1" + object.values "^1.0.4" + sax "~1.2.4" + stable "~0.1.6" + unquote "~1.1.1" + util.promisify "~1.0.0" + +syntax-error@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" + dependencies: + acorn-node "^1.2.0" + +tar@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +tar@^4, tar@^4.4.3, tar@^4.4.4: + version "4.4.6" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + dependencies: + execa "^0.7.0" + +terser@^3.7.3: + version "3.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.8.1.tgz#cb70070ac9e0a71add169dfb63c0a64fca2738ac" + dependencies: + commander "~2.16.0" + source-map "~0.6.1" + source-map-support "~0.5.6" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through2@^2.0.0, through2@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +timers-browserify@^1.0.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" + dependencies: + process "~0.11.0" + +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + dependencies: + setimmediate "^1.0.4" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + +tiny-inflate@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" + +tiny-relative-date@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toml@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb" + +tomlify-j0.4@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz#99414d45268c3a3b8bf38be82145b7bba34b7473" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + +tty-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6, typedarray@~0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +typescript@^2.4.1: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + +uglify-es@^3.3.9: + version "3.3.10" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.10.tgz#8b0b7992cebe20edc26de1bf325cef797b8f3fa5" + dependencies: + commander "~2.14.1" + source-map "~0.6.1" + +uid-number@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +umask@^1.1.0, umask@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + +umd@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" + +undeclared-identifiers@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz#7d850a98887cff4bd0bf64999c014d08ed6d1acc" + dependencies: + acorn-node "^1.3.0" + get-assigned-identifiers "^1.2.0" + simple-concat "^1.0.0" + xtend "^4.0.1" + +unicode-trie@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + +unique-filename@^1.1.0, unique-filename@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" + dependencies: + imurmurhash "^0.1.4" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + +update-notifier@^2.3.0, update-notifier@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + dependencies: + boxen "^1.2.1" + chalk "^2.0.1" + configstore "^3.0.0" + import-lazy "^2.1.0" + is-ci "^1.0.10" + is-installed-globally "^0.1.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +url@^0.11.0, url@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + +uswds@^1.6.3: + version "1.6.7" + resolved "https://registry.yarnpkg.com/uswds/-/uswds-1.6.7.tgz#85ffa94a26da333e7e709b9fbc7292edab04ac82" + dependencies: + "@types/node" "^8.5.5" + array-filter "^1.0.0" + array-foreach "^1.0.2" + browserify "^13.0.0" + classlist-polyfill "^1.0.3" + domready "^1.0.8" + elem-dataset "^1.1.1" + lodash.debounce "^4.0.7" + object-assign "^4.1.1" + receptor "^1.0.0" + resolve-id-refs "^0.1.0" + typescript "^2.4.1" + yargs "^8.0.2" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + +util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +util@^0.10.3, util@~0.10.1: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + dependencies: + inherits "2.0.3" + +uuid@^3.0.0, uuid@^3.1.0, uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +v8-compile-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a" + +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + dependencies: + builtins "^1.0.3" + +vendors@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + +vm-browserify@0.0.4, vm-browserify@~0.0.1: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +vue@^2.5.17: + version "2.5.17" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada" + +wcwidth@^1.0.0, wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + dependencies: + defaults "^1.0.3" + +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" + dependencies: + string-width "^2.1.1" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +worker-farm@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +ws@^5.1.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + dependencies: + async-limiter "~1.0.0" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + dependencies: + camelcase "^4.1.0" + +yargs@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" From 630a3b0cd530a7f4581f31af3d358e47ac9396c7 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 2 Aug 2018 13:51:54 -0400 Subject: [PATCH 093/173] Working parcel setup --- package.json | 5 + static/js/index.js | 4 + static/js/thing.js | 7 + {scss => static/scss}/README.md | 0 {scss => static/scss}/atat.scss | 2 +- {scss => static/scss}/components/_alerts.scss | 0 .../scss}/components/_empty_state.scss | 0 {scss => static/scss}/components/_footer.scss | 0 .../scss}/components/_global_layout.scss | 0 .../scss}/components/_global_navigation.scss | 0 {scss => static/scss}/components/_modal.scss | 0 .../scss}/components/_progress_menu.scss | 4 +- .../scss}/components/_search_bar.scss | 2 +- .../scss}/components/_site_action.scss | 0 {scss => static/scss}/components/_topbar.scss | 0 .../scss}/components/_workspace_layout.scss | 0 {scss => static/scss}/core/_grid.scss | 0 {scss => static/scss}/core/_util.scss | 0 {scss => static/scss}/core/_variables.scss | 0 .../scss}/elements/_action_group.scss | 0 .../scss}/elements/_block_lists.scss | 0 {scss => static/scss}/elements/_buttons.scss | 0 {scss => static/scss}/elements/_diff.scss | 0 .../scss}/elements/_icon_link.scss | 0 {scss => static/scss}/elements/_icons.scss | 0 {scss => static/scss}/elements/_inputs.scss | 0 {scss => static/scss}/elements/_labels.scss | 0 {scss => static/scss}/elements/_panels.scss | 0 {scss => static/scss}/elements/_sidenav.scss | 0 {scss => static/scss}/elements/_tables.scss | 0 .../scss}/elements/_typography.scss | 0 {scss => static/scss}/sections/_login.scss | 0 .../scss}/sections/_member_edit.scss | 0 .../scss}/sections/_project_edit.scss | 0 .../scss}/sections/_projects_list.scss | 0 .../scss}/sections/_request_approval.scss | 0 templates/base.html | 5 +- templates/home.html | 1 + yarn.lock | 391 +++++++++++++++--- 39 files changed, 349 insertions(+), 72 deletions(-) create mode 100644 static/js/index.js create mode 100644 static/js/thing.js rename {scss => static/scss}/README.md (100%) rename {scss => static/scss}/atat.scss (94%) rename {scss => static/scss}/components/_alerts.scss (100%) rename {scss => static/scss}/components/_empty_state.scss (100%) rename {scss => static/scss}/components/_footer.scss (100%) rename {scss => static/scss}/components/_global_layout.scss (100%) rename {scss => static/scss}/components/_global_navigation.scss (100%) rename {scss => static/scss}/components/_modal.scss (100%) rename {scss => static/scss}/components/_progress_menu.scss (96%) rename {scss => static/scss}/components/_search_bar.scss (95%) rename {scss => static/scss}/components/_site_action.scss (100%) rename {scss => static/scss}/components/_topbar.scss (100%) rename {scss => static/scss}/components/_workspace_layout.scss (100%) rename {scss => static/scss}/core/_grid.scss (100%) rename {scss => static/scss}/core/_util.scss (100%) rename {scss => static/scss}/core/_variables.scss (100%) rename {scss => static/scss}/elements/_action_group.scss (100%) rename {scss => static/scss}/elements/_block_lists.scss (100%) rename {scss => static/scss}/elements/_buttons.scss (100%) rename {scss => static/scss}/elements/_diff.scss (100%) rename {scss => static/scss}/elements/_icon_link.scss (100%) rename {scss => static/scss}/elements/_icons.scss (100%) rename {scss => static/scss}/elements/_inputs.scss (100%) rename {scss => static/scss}/elements/_labels.scss (100%) rename {scss => static/scss}/elements/_panels.scss (100%) rename {scss => static/scss}/elements/_sidenav.scss (100%) rename {scss => static/scss}/elements/_tables.scss (100%) rename {scss => static/scss}/elements/_typography.scss (100%) rename {scss => static/scss}/sections/_login.scss (100%) rename {scss => static/scss}/sections/_member_edit.scss (100%) rename {scss => static/scss}/sections/_project_edit.scss (100%) rename {scss => static/scss}/sections/_projects_list.scss (100%) rename {scss => static/scss}/sections/_request_approval.scss (100%) diff --git a/package.json b/package.json index 9a474e0d..4d7b794e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "description": "ATST Stateless Services", "main": "index.js", "scripts": { + "watch": "parcel watch static/js/index.js -d static/assets -o index.js --no-autoinstall", + "build": "parcel build static/js/index.js -d static/assets -o index.js --no-autoinstall", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", @@ -13,5 +15,8 @@ "parcel": "^1.9.7", "uswds": "^1.6.3", "vue": "^2.5.17" + }, + "devDependencies": { + "node-sass": "^4.9.2" } } diff --git a/static/js/index.js b/static/js/index.js new file mode 100644 index 00000000..9cc49957 --- /dev/null +++ b/static/js/index.js @@ -0,0 +1,4 @@ +import classes from '../scss/atat.scss' + +import './thing' + diff --git a/static/js/thing.js b/static/js/thing.js new file mode 100644 index 00000000..033b8cd3 --- /dev/null +++ b/static/js/thing.js @@ -0,0 +1,7 @@ +console.log('hanlo again') +window.onload = function() { + console.log('boop') + const thing = document.querySelector('#hello') + thing.innerHTML = 'hanlo friendo' +} + diff --git a/scss/README.md b/static/scss/README.md similarity index 100% rename from scss/README.md rename to static/scss/README.md diff --git a/scss/atat.scss b/static/scss/atat.scss similarity index 94% rename from scss/atat.scss rename to static/scss/atat.scss index b4ae7797..040cc201 100644 --- a/scss/atat.scss +++ b/static/scss/atat.scss @@ -1,5 +1,5 @@ @import 'core/variables'; -@import '../node_modules/uswds/src/stylesheets/uswds'; +@import '../../node_modules/uswds/src/stylesheets/uswds'; @import 'core/grid'; @import 'core/util'; diff --git a/scss/components/_alerts.scss b/static/scss/components/_alerts.scss similarity index 100% rename from scss/components/_alerts.scss rename to static/scss/components/_alerts.scss diff --git a/scss/components/_empty_state.scss b/static/scss/components/_empty_state.scss similarity index 100% rename from scss/components/_empty_state.scss rename to static/scss/components/_empty_state.scss diff --git a/scss/components/_footer.scss b/static/scss/components/_footer.scss similarity index 100% rename from scss/components/_footer.scss rename to static/scss/components/_footer.scss diff --git a/scss/components/_global_layout.scss b/static/scss/components/_global_layout.scss similarity index 100% rename from scss/components/_global_layout.scss rename to static/scss/components/_global_layout.scss diff --git a/scss/components/_global_navigation.scss b/static/scss/components/_global_navigation.scss similarity index 100% rename from scss/components/_global_navigation.scss rename to static/scss/components/_global_navigation.scss diff --git a/scss/components/_modal.scss b/static/scss/components/_modal.scss similarity index 100% rename from scss/components/_modal.scss rename to static/scss/components/_modal.scss diff --git a/scss/components/_progress_menu.scss b/static/scss/components/_progress_menu.scss similarity index 96% rename from scss/components/_progress_menu.scss rename to static/scss/components/_progress_menu.scss index 3ca7bb72..a675dfb7 100644 --- a/scss/components/_progress_menu.scss +++ b/static/scss/components/_progress_menu.scss @@ -88,7 +88,7 @@ } &--complete:before { - content: url('/static/icons/checkmark.svg'); + content: url('#{$asset-path}/icons/checkmark.svg'); background-color: $color-blue; border: 2px solid $color-blue; font-size: $h6-font-size; @@ -100,4 +100,4 @@ } } -} \ No newline at end of file +} diff --git a/scss/components/_search_bar.scss b/static/scss/components/_search_bar.scss similarity index 95% rename from scss/components/_search_bar.scss rename to static/scss/components/_search_bar.scss index f5c031f8..dbc795d2 100644 --- a/scss/components/_search_bar.scss +++ b/static/scss/components/_search_bar.scss @@ -62,7 +62,7 @@ text-align: center; &:after { - content: url('/static/icons/search.svg'); + content: url('#{$asset-path}/icons/search.svg'); display: inline-block; width: 1.6rem; height: 1.6rem; diff --git a/scss/components/_site_action.scss b/static/scss/components/_site_action.scss similarity index 100% rename from scss/components/_site_action.scss rename to static/scss/components/_site_action.scss diff --git a/scss/components/_topbar.scss b/static/scss/components/_topbar.scss similarity index 100% rename from scss/components/_topbar.scss rename to static/scss/components/_topbar.scss diff --git a/scss/components/_workspace_layout.scss b/static/scss/components/_workspace_layout.scss similarity index 100% rename from scss/components/_workspace_layout.scss rename to static/scss/components/_workspace_layout.scss diff --git a/scss/core/_grid.scss b/static/scss/core/_grid.scss similarity index 100% rename from scss/core/_grid.scss rename to static/scss/core/_grid.scss diff --git a/scss/core/_util.scss b/static/scss/core/_util.scss similarity index 100% rename from scss/core/_util.scss rename to static/scss/core/_util.scss diff --git a/scss/core/_variables.scss b/static/scss/core/_variables.scss similarity index 100% rename from scss/core/_variables.scss rename to static/scss/core/_variables.scss diff --git a/scss/elements/_action_group.scss b/static/scss/elements/_action_group.scss similarity index 100% rename from scss/elements/_action_group.scss rename to static/scss/elements/_action_group.scss diff --git a/scss/elements/_block_lists.scss b/static/scss/elements/_block_lists.scss similarity index 100% rename from scss/elements/_block_lists.scss rename to static/scss/elements/_block_lists.scss diff --git a/scss/elements/_buttons.scss b/static/scss/elements/_buttons.scss similarity index 100% rename from scss/elements/_buttons.scss rename to static/scss/elements/_buttons.scss diff --git a/scss/elements/_diff.scss b/static/scss/elements/_diff.scss similarity index 100% rename from scss/elements/_diff.scss rename to static/scss/elements/_diff.scss diff --git a/scss/elements/_icon_link.scss b/static/scss/elements/_icon_link.scss similarity index 100% rename from scss/elements/_icon_link.scss rename to static/scss/elements/_icon_link.scss diff --git a/scss/elements/_icons.scss b/static/scss/elements/_icons.scss similarity index 100% rename from scss/elements/_icons.scss rename to static/scss/elements/_icons.scss diff --git a/scss/elements/_inputs.scss b/static/scss/elements/_inputs.scss similarity index 100% rename from scss/elements/_inputs.scss rename to static/scss/elements/_inputs.scss diff --git a/scss/elements/_labels.scss b/static/scss/elements/_labels.scss similarity index 100% rename from scss/elements/_labels.scss rename to static/scss/elements/_labels.scss diff --git a/scss/elements/_panels.scss b/static/scss/elements/_panels.scss similarity index 100% rename from scss/elements/_panels.scss rename to static/scss/elements/_panels.scss diff --git a/scss/elements/_sidenav.scss b/static/scss/elements/_sidenav.scss similarity index 100% rename from scss/elements/_sidenav.scss rename to static/scss/elements/_sidenav.scss diff --git a/scss/elements/_tables.scss b/static/scss/elements/_tables.scss similarity index 100% rename from scss/elements/_tables.scss rename to static/scss/elements/_tables.scss diff --git a/scss/elements/_typography.scss b/static/scss/elements/_typography.scss similarity index 100% rename from scss/elements/_typography.scss rename to static/scss/elements/_typography.scss diff --git a/scss/sections/_login.scss b/static/scss/sections/_login.scss similarity index 100% rename from scss/sections/_login.scss rename to static/scss/sections/_login.scss diff --git a/scss/sections/_member_edit.scss b/static/scss/sections/_member_edit.scss similarity index 100% rename from scss/sections/_member_edit.scss rename to static/scss/sections/_member_edit.scss diff --git a/scss/sections/_project_edit.scss b/static/scss/sections/_project_edit.scss similarity index 100% rename from scss/sections/_project_edit.scss rename to static/scss/sections/_project_edit.scss diff --git a/scss/sections/_projects_list.scss b/static/scss/sections/_projects_list.scss similarity index 100% rename from scss/sections/_projects_list.scss rename to static/scss/sections/_projects_list.scss diff --git a/scss/sections/_request_approval.scss b/static/scss/sections/_request_approval.scss similarity index 100% rename from scss/sections/_request_approval.scss rename to static/scss/sections/_request_approval.scss diff --git a/templates/base.html b/templates/base.html index 2414f6f1..aaae0374 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,9 +8,7 @@ {% block title %}JEDI{% endblock %} - {% assets "css" %} - - {% endassets %} + @@ -34,5 +32,6 @@ {% include 'footer.html' %} {% block modal %}{% endblock %} + diff --git a/templates/home.html b/templates/home.html index 0df70037..056d62b8 100644 --- a/templates/home.html +++ b/templates/home.html @@ -5,6 +5,7 @@

    Home

    +
    diff --git a/yarn.lock b/yarn.lock index ca8a5e51..b8e561fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -78,6 +78,10 @@ alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -168,6 +172,10 @@ array-filter@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + array-foreach@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-foreach/-/array-foreach-1.0.2.tgz#cd36e42f0f482108c406b35c3612a8970b2fccea" @@ -222,6 +230,10 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" @@ -1115,6 +1127,21 @@ call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1153,7 +1180,7 @@ caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -chalk@^1.1.3: +chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1544,6 +1571,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -1750,6 +1784,12 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -1783,7 +1823,7 @@ debug@3.1.0, debug@^3.1.0: dependencies: ms "2.0.0" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -2280,6 +2320,13 @@ find-npm-prefix@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -2415,6 +2462,12 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaze@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + dependencies: + globule "^1.0.0" + genfun@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" @@ -2444,6 +2497,10 @@ get-port@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -2469,7 +2526,17 @@ glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.2: +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2490,6 +2557,14 @@ globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" +globule@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" + dependencies: + glob "~7.1.1" + lodash "~4.17.10" + minimatch "~3.0.2" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -2763,10 +2838,20 @@ import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -3074,6 +3159,10 @@ is-url@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -3112,7 +3201,7 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -js-base64@^2.1.9: +js-base64@^2.1.8, js-base64@^2.1.9: version "2.4.8" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" @@ -3315,6 +3404,16 @@ libnpx@^10.2.0: y18n "^4.0.0" yargs "^11.0.0" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -3344,10 +3443,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -3355,37 +3450,23 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - lodash._root@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + lodash.clone@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" -lodash.clonedeep@~4.5.0: +lodash.clonedeep@^4.3.2, lodash.clonedeep@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -3401,9 +3482,9 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" +lodash.mergewith@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" lodash.union@~4.6.0: version "4.6.0" @@ -3417,7 +3498,7 @@ lodash.without@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" -lodash@^4.17.4: +lodash@^4.0.0, lodash@^4.17.4, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -3433,6 +3514,13 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -3498,6 +3586,10 @@ map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -3533,6 +3625,21 @@ mem@^1.1.0: dependencies: mimic-fn "^1.0.0" +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + merge-source-map@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" @@ -3594,7 +3701,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@^3.0.2, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -3707,7 +3814,7 @@ mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.0.7, nan@^2.9.2: +nan@^2.0.7, nan@^2.10.0, nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" @@ -3751,7 +3858,7 @@ node-forge@^0.7.1: version "0.7.5" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" -node-gyp@^3.6.2, node-gyp@^3.7.0: +node-gyp@^3.3.1, node-gyp@^3.6.2, node-gyp@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.7.0.tgz#789478e8f6c45e277aa014f3e28f958f286f9203" dependencies: @@ -3817,6 +3924,30 @@ node-releases@^1.0.0-alpha.10: dependencies: semver "^5.3.0" +node-sass@^4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.2.tgz#5e63fe6bd0f2ae3ac9d6c14ede8620e2b8bdb437" + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash.assign "^4.2.0" + lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.10.0" + node-gyp "^3.3.1" + npmlog "^4.0.0" + request "2.87.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + "nopt@2 || 3", nopt@~3.0.1: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -3830,7 +3961,7 @@ nopt@^4.0.1, nopt@~4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -4092,7 +4223,7 @@ npm@^6.0.1: worker-farm "^1.6.0" write-file-atomic "^2.3.0" -"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.2, npmlog@~4.1.2: +"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@~4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -4229,6 +4360,12 @@ os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -4431,6 +4568,12 @@ path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -4455,6 +4598,14 @@ path-platform@~0.11.15: version "0.11.15" resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -4491,6 +4642,16 @@ pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -5188,6 +5349,13 @@ read-package-tree@^5.2.1: read-package-json "^2.0.0" readdir-scoped-modules "^1.0.0" +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" @@ -5195,6 +5363,14 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" @@ -5209,7 +5385,7 @@ read@1, read@~1.0.1, read@~1.0.7: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -5241,7 +5417,7 @@ readable-stream@~2.0.0: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0: +readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" dependencies: @@ -5268,6 +5444,13 @@ receptor@^1.0.0: matches-selector "^1.0.0" object-assign "^4.1.0" +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + reduce-css-calc@^1.2.6: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" @@ -5361,6 +5544,31 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" +request@2.87.0, request@^2.74.0, request@^2.81.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + "request@>=2.9.0 <2.82.0": version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -5388,31 +5596,6 @@ repeating@^2.0.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.74.0, request@^2.81.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -5509,10 +5692,26 @@ safer-eval@^1.2.3: dependencies: clones "^1.1.0" +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -5782,6 +5981,12 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5887,6 +6092,12 @@ statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -5944,7 +6155,7 @@ strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" -string-width@^1.0.1: +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: @@ -5989,6 +6200,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -5997,6 +6214,12 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -6189,10 +6412,20 @@ tough-cookie@~2.3.0, tough-cookie@~2.3.3: dependencies: punycode "^1.4.1" +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +"true-case-path@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + dependencies: + glob "^6.0.4" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -6456,6 +6689,10 @@ whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -6537,6 +6774,12 @@ yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -6566,6 +6809,24 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" From c4dde6beedc4563e338af19e403225acd0009154 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 2 Aug 2018 14:33:21 -0400 Subject: [PATCH 094/173] Move styles to "styles" directory --- static/js/index.js | 2 +- static/{scss => styles}/README.md | 0 static/{scss => styles}/atat.scss | 0 static/{scss => styles}/components/_alerts.scss | 0 static/{scss => styles}/components/_empty_state.scss | 0 static/{scss => styles}/components/_footer.scss | 0 static/{scss => styles}/components/_global_layout.scss | 0 static/{scss => styles}/components/_global_navigation.scss | 0 static/{scss => styles}/components/_modal.scss | 0 static/{scss => styles}/components/_progress_menu.scss | 0 static/{scss => styles}/components/_search_bar.scss | 0 static/{scss => styles}/components/_site_action.scss | 0 static/{scss => styles}/components/_topbar.scss | 0 static/{scss => styles}/components/_workspace_layout.scss | 0 static/{scss => styles}/core/_grid.scss | 0 static/{scss => styles}/core/_util.scss | 0 static/{scss => styles}/core/_variables.scss | 0 static/{scss => styles}/elements/_action_group.scss | 0 static/{scss => styles}/elements/_block_lists.scss | 0 static/{scss => styles}/elements/_buttons.scss | 0 static/{scss => styles}/elements/_diff.scss | 0 static/{scss => styles}/elements/_icon_link.scss | 0 static/{scss => styles}/elements/_icons.scss | 0 static/{scss => styles}/elements/_inputs.scss | 0 static/{scss => styles}/elements/_labels.scss | 0 static/{scss => styles}/elements/_panels.scss | 0 static/{scss => styles}/elements/_sidenav.scss | 0 static/{scss => styles}/elements/_tables.scss | 0 static/{scss => styles}/elements/_typography.scss | 0 static/{scss => styles}/sections/_login.scss | 0 static/{scss => styles}/sections/_member_edit.scss | 0 static/{scss => styles}/sections/_project_edit.scss | 0 static/{scss => styles}/sections/_projects_list.scss | 0 static/{scss => styles}/sections/_request_approval.scss | 0 34 files changed, 1 insertion(+), 1 deletion(-) rename static/{scss => styles}/README.md (100%) rename static/{scss => styles}/atat.scss (100%) rename static/{scss => styles}/components/_alerts.scss (100%) rename static/{scss => styles}/components/_empty_state.scss (100%) rename static/{scss => styles}/components/_footer.scss (100%) rename static/{scss => styles}/components/_global_layout.scss (100%) rename static/{scss => styles}/components/_global_navigation.scss (100%) rename static/{scss => styles}/components/_modal.scss (100%) rename static/{scss => styles}/components/_progress_menu.scss (100%) rename static/{scss => styles}/components/_search_bar.scss (100%) rename static/{scss => styles}/components/_site_action.scss (100%) rename static/{scss => styles}/components/_topbar.scss (100%) rename static/{scss => styles}/components/_workspace_layout.scss (100%) rename static/{scss => styles}/core/_grid.scss (100%) rename static/{scss => styles}/core/_util.scss (100%) rename static/{scss => styles}/core/_variables.scss (100%) rename static/{scss => styles}/elements/_action_group.scss (100%) rename static/{scss => styles}/elements/_block_lists.scss (100%) rename static/{scss => styles}/elements/_buttons.scss (100%) rename static/{scss => styles}/elements/_diff.scss (100%) rename static/{scss => styles}/elements/_icon_link.scss (100%) rename static/{scss => styles}/elements/_icons.scss (100%) rename static/{scss => styles}/elements/_inputs.scss (100%) rename static/{scss => styles}/elements/_labels.scss (100%) rename static/{scss => styles}/elements/_panels.scss (100%) rename static/{scss => styles}/elements/_sidenav.scss (100%) rename static/{scss => styles}/elements/_tables.scss (100%) rename static/{scss => styles}/elements/_typography.scss (100%) rename static/{scss => styles}/sections/_login.scss (100%) rename static/{scss => styles}/sections/_member_edit.scss (100%) rename static/{scss => styles}/sections/_project_edit.scss (100%) rename static/{scss => styles}/sections/_projects_list.scss (100%) rename static/{scss => styles}/sections/_request_approval.scss (100%) diff --git a/static/js/index.js b/static/js/index.js index 9cc49957..91a30f3e 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -1,4 +1,4 @@ -import classes from '../scss/atat.scss' +import classes from '../styles/atat.scss' import './thing' diff --git a/static/scss/README.md b/static/styles/README.md similarity index 100% rename from static/scss/README.md rename to static/styles/README.md diff --git a/static/scss/atat.scss b/static/styles/atat.scss similarity index 100% rename from static/scss/atat.scss rename to static/styles/atat.scss diff --git a/static/scss/components/_alerts.scss b/static/styles/components/_alerts.scss similarity index 100% rename from static/scss/components/_alerts.scss rename to static/styles/components/_alerts.scss diff --git a/static/scss/components/_empty_state.scss b/static/styles/components/_empty_state.scss similarity index 100% rename from static/scss/components/_empty_state.scss rename to static/styles/components/_empty_state.scss diff --git a/static/scss/components/_footer.scss b/static/styles/components/_footer.scss similarity index 100% rename from static/scss/components/_footer.scss rename to static/styles/components/_footer.scss diff --git a/static/scss/components/_global_layout.scss b/static/styles/components/_global_layout.scss similarity index 100% rename from static/scss/components/_global_layout.scss rename to static/styles/components/_global_layout.scss diff --git a/static/scss/components/_global_navigation.scss b/static/styles/components/_global_navigation.scss similarity index 100% rename from static/scss/components/_global_navigation.scss rename to static/styles/components/_global_navigation.scss diff --git a/static/scss/components/_modal.scss b/static/styles/components/_modal.scss similarity index 100% rename from static/scss/components/_modal.scss rename to static/styles/components/_modal.scss diff --git a/static/scss/components/_progress_menu.scss b/static/styles/components/_progress_menu.scss similarity index 100% rename from static/scss/components/_progress_menu.scss rename to static/styles/components/_progress_menu.scss diff --git a/static/scss/components/_search_bar.scss b/static/styles/components/_search_bar.scss similarity index 100% rename from static/scss/components/_search_bar.scss rename to static/styles/components/_search_bar.scss diff --git a/static/scss/components/_site_action.scss b/static/styles/components/_site_action.scss similarity index 100% rename from static/scss/components/_site_action.scss rename to static/styles/components/_site_action.scss diff --git a/static/scss/components/_topbar.scss b/static/styles/components/_topbar.scss similarity index 100% rename from static/scss/components/_topbar.scss rename to static/styles/components/_topbar.scss diff --git a/static/scss/components/_workspace_layout.scss b/static/styles/components/_workspace_layout.scss similarity index 100% rename from static/scss/components/_workspace_layout.scss rename to static/styles/components/_workspace_layout.scss diff --git a/static/scss/core/_grid.scss b/static/styles/core/_grid.scss similarity index 100% rename from static/scss/core/_grid.scss rename to static/styles/core/_grid.scss diff --git a/static/scss/core/_util.scss b/static/styles/core/_util.scss similarity index 100% rename from static/scss/core/_util.scss rename to static/styles/core/_util.scss diff --git a/static/scss/core/_variables.scss b/static/styles/core/_variables.scss similarity index 100% rename from static/scss/core/_variables.scss rename to static/styles/core/_variables.scss diff --git a/static/scss/elements/_action_group.scss b/static/styles/elements/_action_group.scss similarity index 100% rename from static/scss/elements/_action_group.scss rename to static/styles/elements/_action_group.scss diff --git a/static/scss/elements/_block_lists.scss b/static/styles/elements/_block_lists.scss similarity index 100% rename from static/scss/elements/_block_lists.scss rename to static/styles/elements/_block_lists.scss diff --git a/static/scss/elements/_buttons.scss b/static/styles/elements/_buttons.scss similarity index 100% rename from static/scss/elements/_buttons.scss rename to static/styles/elements/_buttons.scss diff --git a/static/scss/elements/_diff.scss b/static/styles/elements/_diff.scss similarity index 100% rename from static/scss/elements/_diff.scss rename to static/styles/elements/_diff.scss diff --git a/static/scss/elements/_icon_link.scss b/static/styles/elements/_icon_link.scss similarity index 100% rename from static/scss/elements/_icon_link.scss rename to static/styles/elements/_icon_link.scss diff --git a/static/scss/elements/_icons.scss b/static/styles/elements/_icons.scss similarity index 100% rename from static/scss/elements/_icons.scss rename to static/styles/elements/_icons.scss diff --git a/static/scss/elements/_inputs.scss b/static/styles/elements/_inputs.scss similarity index 100% rename from static/scss/elements/_inputs.scss rename to static/styles/elements/_inputs.scss diff --git a/static/scss/elements/_labels.scss b/static/styles/elements/_labels.scss similarity index 100% rename from static/scss/elements/_labels.scss rename to static/styles/elements/_labels.scss diff --git a/static/scss/elements/_panels.scss b/static/styles/elements/_panels.scss similarity index 100% rename from static/scss/elements/_panels.scss rename to static/styles/elements/_panels.scss diff --git a/static/scss/elements/_sidenav.scss b/static/styles/elements/_sidenav.scss similarity index 100% rename from static/scss/elements/_sidenav.scss rename to static/styles/elements/_sidenav.scss diff --git a/static/scss/elements/_tables.scss b/static/styles/elements/_tables.scss similarity index 100% rename from static/scss/elements/_tables.scss rename to static/styles/elements/_tables.scss diff --git a/static/scss/elements/_typography.scss b/static/styles/elements/_typography.scss similarity index 100% rename from static/scss/elements/_typography.scss rename to static/styles/elements/_typography.scss diff --git a/static/scss/sections/_login.scss b/static/styles/sections/_login.scss similarity index 100% rename from static/scss/sections/_login.scss rename to static/styles/sections/_login.scss diff --git a/static/scss/sections/_member_edit.scss b/static/styles/sections/_member_edit.scss similarity index 100% rename from static/scss/sections/_member_edit.scss rename to static/styles/sections/_member_edit.scss diff --git a/static/scss/sections/_project_edit.scss b/static/styles/sections/_project_edit.scss similarity index 100% rename from static/scss/sections/_project_edit.scss rename to static/styles/sections/_project_edit.scss diff --git a/static/scss/sections/_projects_list.scss b/static/styles/sections/_projects_list.scss similarity index 100% rename from static/scss/sections/_projects_list.scss rename to static/styles/sections/_projects_list.scss diff --git a/static/scss/sections/_request_approval.scss b/static/styles/sections/_request_approval.scss similarity index 100% rename from static/scss/sections/_request_approval.scss rename to static/styles/sections/_request_approval.scss From 7377dd1f3f5916046ef95aa9a242de6f473dc896 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 2 Aug 2018 14:54:07 -0400 Subject: [PATCH 095/173] Use flask-webassets to version js/css bundle --- atst/assets.py | 12 ++++++++---- package.json | 2 +- templates/base.html | 8 ++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/atst/assets.py b/atst/assets.py index aef6b35e..6c8fd7e8 100644 --- a/atst/assets.py +++ b/atst/assets.py @@ -4,10 +4,14 @@ from atst.home import home environment = Environment() css = Bundle( - "../scss/atat.scss", - filters="scss", - output="../static/assets/out.%(version)s.css", - depends=("**/*.scss"), + "../static/assets/index.css", + output="../static/assets/styles.%(version)s.css", ) environment.register("css", css) + +js = Bundle( + '../static/assets/index.js', + output='../static/assets/index.%(version)s.js' +) +environment.register('js_all', js) diff --git a/package.json b/package.json index 4d7b794e..421c767b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "watch": "parcel watch static/js/index.js -d static/assets -o index.js --no-autoinstall", - "build": "parcel build static/js/index.js -d static/assets -o index.js --no-autoinstall", + "build": "parcel build static/js/index.js -d static/assets -o index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", diff --git a/templates/base.html b/templates/base.html index aaae0374..acc3e6e7 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,7 +8,9 @@ {% block title %}JEDI{% endblock %} - + {% assets "css" %} + + {% endassets %} @@ -32,6 +34,8 @@ {% include 'footer.html' %} {% block modal %}{% endblock %} - + {% assets "js_all" %} + {% endassets %} From d45b4354f91941e70132d4d467f6c7301aed0cb2 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 3 Aug 2018 09:10:40 -0400 Subject: [PATCH 109/173] Remove styles and js from assets --- static/js/index.js | 4 - static/js/thing.js | 7 - static/styles/README.md | 82 ------ static/styles/atat.scss | 36 --- static/styles/components/_alerts.scss | 76 ------ static/styles/components/_empty_state.scss | 27 -- static/styles/components/_footer.scss | 6 - static/styles/components/_global_layout.scss | 36 --- .../styles/components/_global_navigation.scss | 30 --- static/styles/components/_modal.scss | 47 ---- static/styles/components/_progress_menu.scss | 103 -------- static/styles/components/_search_bar.scss | 72 ------ static/styles/components/_site_action.scss | 15 -- static/styles/components/_topbar.scss | 71 ------ .../styles/components/_workspace_layout.scss | 26 -- static/styles/core/_grid.scss | 45 ---- static/styles/core/_util.scss | 33 --- static/styles/core/_variables.scss | 167 ------------ static/styles/elements/_action_group.scss | 19 -- static/styles/elements/_block_lists.scss | 90 ------- static/styles/elements/_buttons.scss | 5 - static/styles/elements/_diff.scss | 36 --- static/styles/elements/_icon_link.scss | 66 ----- static/styles/elements/_icons.scss | 52 ---- static/styles/elements/_inputs.scss | 241 ------------------ static/styles/elements/_labels.scss | 34 --- static/styles/elements/_panels.scss | 67 ----- static/styles/elements/_sidenav.scss | 87 ------- static/styles/elements/_tables.scss | 92 ------- static/styles/elements/_typography.scss | 59 ----- static/styles/sections/_login.scss | 3 - static/styles/sections/_member_edit.scss | 41 --- static/styles/sections/_project_edit.scss | 19 -- static/styles/sections/_projects_list.scss | 22 -- static/styles/sections/_request_approval.scss | 97 ------- 35 files changed, 1913 deletions(-) delete mode 100644 static/js/index.js delete mode 100644 static/js/thing.js delete mode 100644 static/styles/README.md delete mode 100644 static/styles/atat.scss delete mode 100644 static/styles/components/_alerts.scss delete mode 100644 static/styles/components/_empty_state.scss delete mode 100644 static/styles/components/_footer.scss delete mode 100644 static/styles/components/_global_layout.scss delete mode 100644 static/styles/components/_global_navigation.scss delete mode 100644 static/styles/components/_modal.scss delete mode 100644 static/styles/components/_progress_menu.scss delete mode 100644 static/styles/components/_search_bar.scss delete mode 100644 static/styles/components/_site_action.scss delete mode 100644 static/styles/components/_topbar.scss delete mode 100644 static/styles/components/_workspace_layout.scss delete mode 100644 static/styles/core/_grid.scss delete mode 100644 static/styles/core/_util.scss delete mode 100644 static/styles/core/_variables.scss delete mode 100644 static/styles/elements/_action_group.scss delete mode 100644 static/styles/elements/_block_lists.scss delete mode 100644 static/styles/elements/_buttons.scss delete mode 100644 static/styles/elements/_diff.scss delete mode 100644 static/styles/elements/_icon_link.scss delete mode 100644 static/styles/elements/_icons.scss delete mode 100644 static/styles/elements/_inputs.scss delete mode 100644 static/styles/elements/_labels.scss delete mode 100644 static/styles/elements/_panels.scss delete mode 100644 static/styles/elements/_sidenav.scss delete mode 100644 static/styles/elements/_tables.scss delete mode 100644 static/styles/elements/_typography.scss delete mode 100644 static/styles/sections/_login.scss delete mode 100644 static/styles/sections/_member_edit.scss delete mode 100644 static/styles/sections/_project_edit.scss delete mode 100644 static/styles/sections/_projects_list.scss delete mode 100644 static/styles/sections/_request_approval.scss diff --git a/static/js/index.js b/static/js/index.js deleted file mode 100644 index 91a30f3e..00000000 --- a/static/js/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import classes from '../styles/atat.scss' - -import './thing' - diff --git a/static/js/thing.js b/static/js/thing.js deleted file mode 100644 index 033b8cd3..00000000 --- a/static/js/thing.js +++ /dev/null @@ -1,7 +0,0 @@ -console.log('hanlo again') -window.onload = function() { - console.log('boop') - const thing = document.querySelector('#hello') - thing.innerHTML = 'hanlo friendo' -} - diff --git a/static/styles/README.md b/static/styles/README.md deleted file mode 100644 index 2df6de9d..00000000 --- a/static/styles/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# Styling AT-ST - -AT-ST's user interface components are based on the (U.S. Web Design System)[https://designsystem.digital.gov/components/]. Please refer there when deciding how to implement a UI feature. - -## CSS Architecture -### (Copied from https://github.com/uswds/uswds#css-architecture) -## CSS architecture - -* The CSS foundation of this site is built with the **[Sass](https://sass-lang.com)** preprocessor language. -* Uses **[Bourbon](http://bourbon.io/)** for its simple and lightweight Sass mixin library, and the **[Neat](http://neat.bourbon.io/)** library for the grid framework. Bourbon and Neat are open-source products from **[thoughtbot](https://thoughtbot.com/)**. -* The CSS organization and naming conventions follow **[18F’s CSS Front End Guide](https://frontend.18f.gov/css/)**. -* CSS selectors are **prefixed** with `usa` (For example: `.usa-button`). This identifier helps the design system avoid conflicts with other styles on a site which are not part of the U.S. Web Design System. -* Uses a **[modified BEM](https://frontend.18f.gov/css/naming/)** approach created by 18F for naming CSS selectors. Objects in CSS are separated by single dashes. Multi-word objects are separated by an underscore (For example: `.usa-button-cool_feature-active`). -* Uses **modular CSS** for scalable, modular, and flexible code. -* Uses **nesting** when appropriate. Nest minimally with up to two levels of nesting. -* Hard-coded magic numbers are avoided and, if necessary, defined in the `core/variables` scss file. -* Media queries are built **mobile first**. -* **Spacing units** are as much as possible defined as rem or em units so they scale appropriately with text size. Pixels can be used for detail work and should not exceed 5px (For example: 3px borders). - -**For more information, visit:** -[18F’s CSS Front End Guide](https://frontend.18f.gov/css/) - -Overrides and Modifications ---- - -When making modifications to the default USWDS components, please refer to the original source, and make a `.scss` file of the same name. Annotate the top of the file with a reference to the USWDS documentation and source code. - -Row/Column System ---- - -A simple, flexbox-powered row/column system. - -``` -
    -
    -
    -
    -
    -``` - -To make a column expand to fill up all available space relative to its sibling columns: - -``` -
    -
    -
    -
    -
    -``` - -To add uniform padding to rows and columns: - -``` -
    -
    -
    -
    -
    -``` - -Layouts and behaviors for specific row/col use cases should be handled on a case by case basis: - -``` -
    -
    -
    -
    -
    - -... - -.foo.row { - .col { - flex: 1; - } - .foo__bar { - flex: 2; - } -} -``` - -Page templates that inherit from the `base.html` template should render `.col` elements at their top level, with no other wrapping elements. diff --git a/static/styles/atat.scss b/static/styles/atat.scss deleted file mode 100644 index 040cc201..00000000 --- a/static/styles/atat.scss +++ /dev/null @@ -1,36 +0,0 @@ -@import 'core/variables'; -@import '../../node_modules/uswds/src/stylesheets/uswds'; - -@import 'core/grid'; -@import 'core/util'; - -@import 'elements/typography'; -@import 'elements/icons'; -@import 'elements/icon_link'; -@import 'elements/inputs'; -@import 'elements/buttons'; -@import 'elements/panels'; -@import 'elements/block_lists'; -@import 'elements/tables'; -@import 'elements/sidenav'; -@import 'elements/action_group'; -@import 'elements/labels'; -@import 'elements/diff'; - -@import 'components/topbar'; -@import 'components/global_layout'; -@import 'components/global_navigation'; -@import 'components/workspace_layout'; -@import 'components/site_action'; -@import 'components/empty_state'; -@import 'components/alerts'; -@import 'components/modal'; -@import 'components/footer'; -@import 'components/progress_menu.scss'; -@import 'components/search_bar'; - -@import 'sections/login'; -@import 'sections/request_approval'; -@import 'sections/projects_list'; -@import 'sections/project_edit'; -@import 'sections/member_edit'; diff --git a/static/styles/components/_alerts.scss b/static/styles/components/_alerts.scss deleted file mode 100644 index f48042b9..00000000 --- a/static/styles/components/_alerts.scss +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Alerts - * @see https://designsystem.digital.gov/components/alerts/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/components/_alerts.scss - */ - -@mixin alert { - padding: $gap * 2; - border-left-width: $gap / 2; - border-left-style: solid; - @include panel-margin; -} - -@mixin alert-level($level) { - $background-color: $color-aqua-lightest; - $border-color: $color-blue; - - @if $level == 'success' { - $background-color: $color-green-lightest; - $border-color: $color-green; - - } @else if $level == 'warning' { - $background-color: $color-gold-lightest; - $border-color: $color-gold; - - } @else if $level == 'error' { - $background-color: $color-red-lightest; - $border-color: $color-red; - } - - background-color: $background-color; - border-color: $border-color; - display: flex; - flex-direction: row; - align-items: flex-start; - - .alert__icon { - @include icon-color($border-color); - flex-grow: 0; - flex-shrink: 0; - margin-right: $gap * 2; - margin-left: 0; - } - - .alert__title { - @include h3; - margin-top: 0; - } - - .alert__content { - .alert__message { - &:last-child { - > *:last-child { - margin-bottom: 0; - } - } - } - } -} - -.alert { - @include alert; - @include alert-level('info'); - - &.alert--success { - @include alert-level('success'); - } - - &.alert--warning { - @include alert-level('warning'); - } - - &.alert--error { - @include alert-level('error'); - } -} diff --git a/static/styles/components/_empty_state.scss b/static/styles/components/_empty_state.scss deleted file mode 100644 index be8675ad..00000000 --- a/static/styles/components/_empty_state.scss +++ /dev/null @@ -1,27 +0,0 @@ -.empty-state { - text-align: center; - padding: 6rem ($gap * 2) 0; - display: flex; - flex-direction: column; - align-items: center; - - @include media($medium-screen) { - padding: 8rem ($gap * 4) 0; - } - - .icon { - @include icon-size(50); - @include icon-color($color-gray-light); - } - - p { - @include h2; - line-height: 1.2; - max-width: 15em; - color: $color-gray; - - @include media($large-screen) { - @include h1; - } - } -} diff --git a/static/styles/components/_footer.scss b/static/styles/components/_footer.scss deleted file mode 100644 index 964ff393..00000000 --- a/static/styles/components/_footer.scss +++ /dev/null @@ -1,6 +0,0 @@ -.app-footer { - background-color: $color-gray-lightest; - border-top: 1px solid $color-gray-lighter; - padding-left: $gap*4; - padding-bottom: $gap*2; -} diff --git a/static/styles/components/_global_layout.scss b/static/styles/components/_global_layout.scss deleted file mode 100644 index d79890c5..00000000 --- a/static/styles/components/_global_layout.scss +++ /dev/null @@ -1,36 +0,0 @@ -body { - background-color: $color-gray-lightest; - display: flex; - flex-direction: column; - justify-content: flex-start; - min-height: 100vh; - - > footer { - margin-top: auto; - } - - &.modalOpen { - overflow-y: hidden; - } -} - -.global-layout { - display: flex; - flex-wrap: nowrap; - flex-grow: 1; - - .global-navigation { - margin-top: -1px; - } - - .global-panel-container { - margin: $gap; - max-width: $site-max-width; - overflow-x: hidden; - flex-grow: 1; - - @include media($medium-screen) { - margin: $gap * 2; - } - } -} diff --git a/static/styles/components/_global_navigation.scss b/static/styles/components/_global_navigation.scss deleted file mode 100644 index b975270a..00000000 --- a/static/styles/components/_global_navigation.scss +++ /dev/null @@ -1,30 +0,0 @@ -.global-navigation { - background-color: $color-white; - - .sidenav__link { - padding-right: $gap; - - @include media($large-screen) { - padding-right: $gap * 2; - } - } - - .sidenav__link-label { - @include hide; - - @include media($large-screen) { - @include unhide; - padding-left: $gap; - } - } - - &.global-navigation__context--workspace { - .sidenav__link { - padding-right: $gap; - } - - .sidenav__link-label { - @include hide; - } - } -} diff --git a/static/styles/components/_modal.scss b/static/styles/components/_modal.scss deleted file mode 100644 index 868476b9..00000000 --- a/static/styles/components/_modal.scss +++ /dev/null @@ -1,47 +0,0 @@ -.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; - } - } - } -} diff --git a/static/styles/components/_progress_menu.scss b/static/styles/components/_progress_menu.scss deleted file mode 100644 index a675dfb7..00000000 --- a/static/styles/components/_progress_menu.scss +++ /dev/null @@ -1,103 +0,0 @@ -.progress-menu { - display: block; - - ul { - list-style: none; - margin: 0; - padding: 0; - } - - &--three { - .progress-menu__item { - width: 32%; - } - } - - &--four { - .progress-menu__item { - width: 24%; - } - } - - &--five { - .progress-menu__item { - width: 19%; - } - } - - &__item { - display: inline-block; - font-weight: $font-bold; - position: relative; - vertical-align: top; - - a { - display: block; - position: relative; - padding: ($gap * 4) ($gap * 2); - margin: 0 ($gap * 2); - text-decoration: none; - text-align: center; - z-index: 2; - color: $color-black; - } - - a.active { - color: $color-blue; - } - - - - &:first-child:after { - display: none; - } - - &:after { - display: inline-block; - height: 1px; - content: " "; - color: $color-gray-lightest; - text-shadow: none; - background-color: $color-gray-light; - position: absolute; - top: 1.1rem; - width: 100%; - right: 50%; - border-right: 2.2rem solid transparent; - border-left: 2.2rem solid transparent; - background-clip: padding-box; - z-index: 1; - } - - &:before { - content: ""; - display: block; - text-align: center; - width: 2rem; - height: 2rem; - border: 1px solid $color-gray; - border-radius: 100%; - position: absolute; - left: 50%; - margin-left: -1rem; - z-index: 1; - } - - &--active:before { - border: 2px solid $color-blue; - } - - &--complete:before { - content: url('#{$asset-path}/icons/checkmark.svg'); - background-color: $color-blue; - border: 2px solid $color-blue; - font-size: $h6-font-size; - padding: 1px 2px; - } - - &--incomplete:before { - border: 2px solid $color-gray-light; - } - - } -} diff --git a/static/styles/components/_search_bar.scss b/static/styles/components/_search_bar.scss deleted file mode 100644 index dbc795d2..00000000 --- a/static/styles/components/_search_bar.scss +++ /dev/null @@ -1,72 +0,0 @@ -.search-bar { - @include grid-row; - @include panel-base; - @include panel-theme-default; - @include panel-margin; - padding: $gap; - flex-wrap: wrap; - - .usa-input { - margin: 0; - flex-grow: 1; - flex-shrink: 0; - flex-basis: 100%; - height: $search-input-height; - position: relative; - margin-top: $gap; - - @include media($large-screen) { - flex-shrink: 1; - flex-basis: auto; - margin-top: 0; - margin-left: $gap; - } - - label { - @include hide; - } - - &:first-child { - margin-left: 0; - margin-top: 0; - } - } - - .search-input { - @include media($medium-screen) { - flex-basis: 50%; - } - - @media (min-width:800px) and (max-width:900px) { - flex-basis: auto; - } - - input[type='search'] { - width: auto; - height: $search-input-height; - width: calc(100% - #{$search-button-width}); - max-width: none; - font-size: 1.6rem; - } - - button { - position: absolute; - top: 0; - right: 0; - margin: 0; - padding: 0; - height: $search-input-height; - width: $search-button-width; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - text-align: center; - - &:after { - content: url('#{$asset-path}/icons/search.svg'); - display: inline-block; - width: 1.6rem; - height: 1.6rem; - } - } - } -} diff --git a/static/styles/components/_site_action.scss b/static/styles/components/_site_action.scss deleted file mode 100644 index 98af0b18..00000000 --- a/static/styles/components/_site_action.scss +++ /dev/null @@ -1,15 +0,0 @@ -.site-action { - border-bottom: 1px solid $color-gray-lightest; - display: block; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - margin-top: 0.25rem; - - a { - font-size: 1.3rem; - text-transform: uppercase; - text-decoration: none; - color: $color-primary !important; - } - -} \ No newline at end of file diff --git a/static/styles/components/_topbar.scss b/static/styles/components/_topbar.scss deleted file mode 100644 index e56a95fa..00000000 --- a/static/styles/components/_topbar.scss +++ /dev/null @@ -1,71 +0,0 @@ -.topbar { - background-color: $color-white; - border-bottom: 1px solid $color-black; - - .topbar__navigation { - display: flex; - flex-direction: row; - align-items: stretch; - justify-content: space-between; - - .topbar__link { - color: $color-black; - display: inline-flex; - align-items: center; - height: $topbar-height; - padding: 0 ($gap * 2); - text-decoration: none; - - .topbar__link-label { - @include h5; - } - - .topbar__link-icon { - margin-left: $gap; - } - - &.topbar__link--shield { - width: $icon-bar-width; - justify-content: center; - padding: 0; - - .topbar__link-icon { - margin: 0; - } - } - - &:hover { - background-color: $color-primary-darker; - color: $color-white; - - .topbar__link-icon { - @include icon-style-inverted; - } - } - } - - .topbar__context { - display: flex; - flex-grow: 1; - flex-direction: row; - align-items: stretch; - justify-content: space-between; - - &.topbar__context--workspace { - background-color: $color-primary; - - .topbar__link { - color: $color-white; - - .topbar__link-icon { - @include icon-style-inverted; - } - - &:hover { - background-color: $color-primary-darker; - } - } - } - } - } -} diff --git a/static/styles/components/_workspace_layout.scss b/static/styles/components/_workspace_layout.scss deleted file mode 100644 index e2cf4c24..00000000 --- a/static/styles/components/_workspace_layout.scss +++ /dev/null @@ -1,26 +0,0 @@ -.workspace-panel-container { - @include media($large-screen) { - @include grid-row; - } -} - -.workspace-navigation { - @include panel-margin; - - ul { - display: flex; - flex-wrap: wrap; - li { - flex-grow: 1; - } - } - - @include media($large-screen) { - width: 20rem; - margin-right: $gap * 2; - - ul { - display: block; - } - } -} diff --git a/static/styles/core/_grid.scss b/static/styles/core/_grid.scss deleted file mode 100644 index b24327c3..00000000 --- a/static/styles/core/_grid.scss +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Grid - * @see https://designsystem.digital.gov/components/grids/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/core/_grid.scss - */ - -// Roll our own simple grid system -// USWDS grid system is fairly outdated and does not serve the needs of this project -// We are implementing a simple flexbox row/column system - -@mixin grid-row { - display: flex; - flex-direction: row; - flex-wrap: nowrap; -} - -@mixin grid-pad { - @include padding(null $site-margins-mobile); - - @include media($medium-screen) { - @include padding(null $site-margins); - } -} - -.row { - @include grid-row; - - &.row--pad { - @include grid-pad; - } - - &.row--max { - max-width: $site-max-width; - } -} - -.col { - &.col--pad { - @include grid-pad; - } - - &.col--grow { - flex-grow: 1; - } -} diff --git a/static/styles/core/_util.scss b/static/styles/core/_util.scss deleted file mode 100644 index 48957b6c..00000000 --- a/static/styles/core/_util.scss +++ /dev/null @@ -1,33 +0,0 @@ -.nowrap { - white-space: nowrap; -} - -@mixin hide { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.hide { - @include hide; -} - -@mixin unhide { - border: unset; - clip: unset; - height: unset; - margin: unset; - overflow: unset; - padding: unset; - position: unset; - width: unset; -} - -@mixin line-max { - max-width: 45em; -} diff --git a/static/styles/core/_variables.scss b/static/styles/core/_variables.scss deleted file mode 100644 index 79c0e759..00000000 --- a/static/styles/core/_variables.scss +++ /dev/null @@ -1,167 +0,0 @@ -/* - * AT-ST Variables - * =================================================== - */ - -$gap: 0.8rem; // 8px at 10px $em-base -$topbar-height: 4.8rem; -$icon-bar-width: 4.0rem; -$icon-size-small: 2.4rem; -$hover-transition-time: 0.2s; -$search-input-height: 4.4rem; -$search-button-width: 5.0rem; - -/* - * USWDS Variables - * @see https://github.com/uswds/uswds/blob/develop/src/stylesheets/core/_variables.scss - * =================================================== - */ - -// $em-base: 10px; This is not defaulted in USWDS, so we cant override it -$base-font-size: 1.7rem; -$small-font-size: 1.4rem; -$lead-font-size: 2rem; -$title-font-size: 5.2rem; -$h1-font-size: 4rem; -$h2-font-size: 3rem; -$h3-font-size: 2rem; -$h4-font-size: 1.7rem; -$h5-font-size: 1.5rem; -$h6-font-size: 1.3rem; -$base-line-height: 1.5; -$heading-line-height: 1.3; -$lead-line-height: 1.7; - -$font-sans: 'Source Sans Pro', sans-serif; -$font-serif: 'Merriweather', serif; - -$font-normal: 400; -$font-bold: 700; - -// Color -$color-blue: #0071bc; -$color-blue-darker: #205493; -$color-blue-darkest: #112e51; - -$color-aqua: #02bfe7; -$color-aqua-dark: #00a6d2; -$color-aqua-darkest: #046b99; -$color-aqua-light: #9bdaf1; -$color-aqua-lightest: #e1f3f8; - -$color-red: #e31c3d; -$color-red-dark: #cd2026; -$color-red-darkest: #981b1e; -$color-red-light: #e59393; -$color-red-lightest: #f9dede; - -$color-white: #ffffff; -$color-black: #000000; -$color-black-light: #212121; - -$color-gray-dark: #323a45; -$color-gray: #5b616b; -$color-gray-medium: #757575; -$color-gray-light: #aeb0b5; -$color-gray-lighter: #d6d7d9; -$color-gray-lightest: #f1f1f1; - -$color-gray-warm-dark: #494440; -$color-gray-warm-light: #e4e2e0; -$color-gray-cool-light: #dce4ef; - -$color-gold: #fdb81e; -$color-gold-light: #f9c642; -$color-gold-lighter: #fad980; -$color-gold-lightest: #fff1d2; - -$color-green: #2e8540; -$color-green-light: #4aa564; -$color-green-lighter: #94bfa2; -$color-green-lightest: #e7f4e4; - -$color-cool-blue: #205493; -$color-cool-blue-light: #4773aa; -$color-cool-blue-lighter: #8ba6ca; -$color-cool-blue-lightest: #dce4ef; - -$color-purple: #4c2c92; - -// Functional colors -$color-primary: $color-blue; -$color-primary-darker: $color-blue-darker; -$color-primary-darkest: $color-blue-darkest; - -$color-primary-alt: $color-aqua; -$color-primary-alt-dark: $color-aqua-dark; -$color-primary-alt-darkest: $color-aqua-darkest; -$color-primary-alt-light: $color-aqua-light; -$color-primary-alt-lightest: $color-aqua-lightest; - -$color-secondary: $color-red; -$color-secondary-dark: $color-red-dark; -$color-secondary-darkest: $color-red-darkest; -$color-secondary-light: $color-red-light; -$color-secondary-lightest: $color-red-lightest; - -$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); - -// Mobile First Breakpoints -$small-screen: 481px; -$medium-screen: 600px; -$large-screen: 800px; -$xlarge-screen: 1200px; - -// Grid column counts by screen size -$grid-columns-small: 1; -$grid-columns-medium: 6; -$grid-columns-large: 12; - -// @media single-keyword helpers -// $small: new-breakpoint(min-width $small-screen $grid-columns-small); -// $medium: new-breakpoint(min-width $medium-screen $grid-columns-medium); -// $large: new-breakpoint(min-width $large-screen $grid-columns-large); - -// Set the base path for assets (used for font and image paths below) -$asset-path: '../'; - -// Relative font and image file paths -$font-path: '#{$asset-path}fonts'; -$image-path: '#{$asset-path}img'; - -// Set $asset-pipeline to true if you're using the Rails Asset Pipeline -$asset-pipeline: false; - -// Magic Numbers -$text-max-width: 66ch; // 66 characters per line -$lead-max-width: 77rem; -$site-max-width: 1200px; // previously 1040px; -$site-margins: $gap; // previously 3rem; -$site-margins-mobile: $gap / 2; // previously 1.5rem; -$article-max-width: 600px; -$input-max-width: 46rem; -$label-border-radius: 2px; -$checkbox-border-radius: 2px; -$border-radius: 3px; -$button-border-radius: 5px; -$box-shadow: 0 0 2px $color-shadow; -$focus-outline: 2px dotted $color-gray-light; -$focus-spacing: 3px; -$nav-width: 300px; // previously 951px; -$sidenav-current-border-width: 0.4rem; // must be in rem for math - -// 44 x 44 pixels hit target following Apple iOS Human Interface -// Guidelines -$hit-area: 4.4rem; - -$spacing-x-small: 0.5rem; -$spacing-small: 1rem; -$spacing-md-small: 1.5rem; -$spacing-medium: 2rem; -$spacing-large: 3rem; diff --git a/static/styles/elements/_action_group.scss b/static/styles/elements/_action_group.scss deleted file mode 100644 index acf2c1fc..00000000 --- a/static/styles/elements/_action_group.scss +++ /dev/null @@ -1,19 +0,0 @@ -.action-group { - display: flex; - flex-direction: row-reverse; - align-items: center; - margin-top: $gap * 4; - - .usa-button, - a { - margin: 0 0 0 ($gap * 2); - - @include media($medium-screen) { - margin: 0 0 0 ($gap * 4); - } - } - - &:last-child { - margin-bottom: $gap * 3; - } -} diff --git a/static/styles/elements/_block_lists.scss b/static/styles/elements/_block_lists.scss deleted file mode 100644 index 6cb24d11..00000000 --- a/static/styles/elements/_block_lists.scss +++ /dev/null @@ -1,90 +0,0 @@ -@mixin block-list { - @include panel-margin; - - > ul { - list-style: none; - margin: 0; - padding: 0; - } -} - -@mixin block-list-header { - @include panel-base; - @include panel-theme-default; - padding: $gap * 2; - display: flex; - flex-direction: row; - justify-content: space-between; -} - -@mixin block-list__title { - @include h4; - margin: 0; -} - -@mixin block-list__footer { - @include panel-base; - @include panel-theme-default; - padding: $gap * 2; - display: flex; - flex-direction: row-reverse; - justify-content: space-between; - - .icon-link { - &:first-child { - margin-right: -$gap; - } - } -} - -@mixin block-list-item { - @include panel-base; - margin: 0; - padding: $gap * 2; - border-top: 0; - border-bottom: 1px dashed $color-gray-light; - - @at-root li#{&} { - &:last-child { - border-bottom-style: solid; - } - } -} - - -.block-list { - @include block-list; - - .icon-link { - margin: -$gap 0; - } - - .icon-link, - .label { - &:first-child { - margin-left: -$gap; - } - - &:last-child { - margin-right: -$gap; - } - - } -} - -.block-list__header { - @include block-list-header; -} - -.block-list__title { - @include block-list__title; -} - -.block-list__item { - @include block-list-item; -} - -.block-list__footer { - @include block-list__footer; - border-top: 0; -} diff --git a/static/styles/elements/_buttons.scss b/static/styles/elements/_buttons.scss deleted file mode 100644 index c4bf4337..00000000 --- a/static/styles/elements/_buttons.scss +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Buttons - * @see https://designsystem.digital.gov/components/buttons/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_buttons.scss - */ diff --git a/static/styles/elements/_diff.scss b/static/styles/elements/_diff.scss deleted file mode 100644 index 85ac4002..00000000 --- a/static/styles/elements/_diff.scss +++ /dev/null @@ -1,36 +0,0 @@ -[class*='diff--'] { - border-left-style: solid; - border-left-width: ($gap / 2); - padding-left: $gap / 2; - margin: ($gap / 2) 0; - - &::before { - font-weight: bold; - padding-right: $gap; - display: inline-block; - width: 1.8rem; - text-align: center; - } -} - -.diff--removed { - background-color: $color-red-lightest; - border-left-color: $color-red-dark; - text-decoration: line-through; - text-decoration-color: $color-overlay; - - &::before { - content: '-'; - color: $color-red-dark; - } -} - -.diff--added { - background-color: $color-aqua-lightest; - border-left-color: $color-aqua-dark; - - &::before { - content: '+'; - color: $color-aqua-dark; - } -} diff --git a/static/styles/elements/_icon_link.scss b/static/styles/elements/_icon_link.scss deleted file mode 100644 index 00daae3f..00000000 --- a/static/styles/elements/_icon_link.scss +++ /dev/null @@ -1,66 +0,0 @@ -@mixin icon-link-color($color: $color-blue, $hover-color: $color-aqua-lightest) { - color: $color; - - &:hover { - background-color: $hover-color; - color: $color; - } - - .icon { - @include icon-color($color); - } -} - -@mixin icon-link { - @include icon-link-color($color-primary); - @include h5; - display: inline-flex; - flex-direction: row; - align-items: center; - padding: $gap; - text-decoration: none; - background: none; - transition: background-color $hover-transition-time; - border-radius: $gap / 2; - - .icon { - @include icon-color($color-primary); - @include icon-size(12); - margin-right: $gap; - } -} - -@mixin icon-link-large { - @include h4; - font-weight: normal; - - .icon { - @include icon-size(16); - margin-right: $gap * 2; - } -} - -@mixin icon-link-vertical { - flex-direction: column; - - .icon { - margin: 0 $gap $gap; - } -} - -.icon-link { - @include icon-link; - @include icon-link-color($color-primary); - - &.icon-link--vertical { - @include icon-link-vertical; - } - - &.icon-link--large { - @include icon-link-large; - } - - &.icon-link--danger { - @include icon-link-color($color-red, $color-red-lightest); - } -} diff --git a/static/styles/elements/_icons.scss b/static/styles/elements/_icons.scss deleted file mode 100644 index 34b35a8c..00000000 --- a/static/styles/elements/_icons.scss +++ /dev/null @@ -1,52 +0,0 @@ -@mixin icon { - display: inline-flex; - - > svg { - width: 100%; - height: 100%; - * { - transition: fill $hover-transition-time; - } - } -} - -@mixin icon-size($size) { - $icon-size: $size * .1rem; - width: $icon-size; - height: auto; - margin: $icon-size / 4; -} - -@mixin icon-color($color) { - > svg * { - fill: $color; - } -} - -@mixin icon-style-default { - @include icon-color($color-black); -} - -@mixin icon-style-active { - @include icon-color($color-primary); -} - -@mixin icon-style-inverted { - > svg * { - fill: $color-white; - } -} - -.icon { - @include icon; - @include icon-size(16); - @include icon-style-default; - - &.icon--tiny { - @include icon-size(10); - } - - &.icon--large { - @include icon-size(24); - } -} diff --git a/static/styles/elements/_inputs.scss b/static/styles/elements/_inputs.scss deleted file mode 100644 index 459e907d..00000000 --- a/static/styles/elements/_inputs.scss +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Inputs - * @see https://designsystem.digital.gov/components/form-controls/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_inputs.scss - */ - -@mixin input-icon { - width: 1.6rem; - height: 1.6rem; - display: block; -} - -@mixin input-state($state) { - $border-width: 1px; - $state-color: $color-gray; - - @if $state == 'error' { - $border-width: 2px; - $state-color: $color-red; - - } @else if $state == 'warning' { - $border-width: 2px; - $state-color: $color-gold; - - } @else if $state == 'success' { - $border-width: 2px; - $state-color: $color-green; - } - - .icon { - @include icon-color($state-color); - } - - .usa-input__message { - color: $state-color; - } - - input, - textarea, - select { - border-color: $state-color; - border-width: $border-width; - } - - fieldset { - input[type='radio'] { - + label::before { - box-shadow: 0 0 0 1px $color-white, 0 0 0 3px $color-red; - } - } - - input[type='checkbox'] { - + label::before { - box-shadow: 0 0 0 2px $color-red; - } - } - } -} - -.usa-input { - margin: ($gap * 4) ($gap * 2) ($gap * 4) 0; - - @include media($medium-screen) { - margin: ($gap * 4) 0; - } - - label { - padding: 0 0 $gap 0; - margin: 0; - @include h4; - @include line-max; - position: relative; - - .usa-input__help { - display: block; - @include h5; - font-weight: normal; - padding-top: $gap / 2; - @include line-max; - } - - .icon { - position: absolute; - left: 100%; - top: 100%; - margin-top: 1.4rem; - margin-left: $gap; - } - } - - input, - textarea, - select { - @include line-max; - margin: 0; - } - - .usa-input__choices { // checkbox & radio sets - legend { - padding: 0 0 $gap 0; - @include h4; - - .icon { - vertical-align: middle; - } - } - - ul { - list-style: none; - margin: 0; - padding: 0; - - > li { - margin: 0; - - [type='radio'] + label, - [type='checkbox'] + label { - margin: 0; - } - } - } - - label { - font-weight: normal; - margin: 0; - } - - .usa-input__message { - display: block; - } - - &.usa-input__choices--inline { - label { - display: inline-block; - padding-right: $gap * 3; - } - } - } - - .usa-input__message { - @include h5; - display: inline-block; - padding-top: $gap; - } - - &.usa-input--error { - @include input-state('error'); - } - - &.usa-input--warning { - @include input-state('warning'); - } - - &.usa-input--success { - @include input-state('success'); - } -} - -select { - border-radius: 0; - -webkit-appearance: none; - -moz-appearance: none; -} - -.usa-date-input label { - margin-top: 0; -} - -.input-label { - margin-top: 1rem; -} - -.usa-fieldset-inputs { - margin-top: 2.25rem; - - label:first-child { - 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; - } - -} - - -// Form Grid -.form-row { - margin: ($gap * 4) 0; - - .form-col { - flex-grow: 1; - - &:first-child .usa-input { - &:first-child { - margin-top: 0; - } - } - - &:last-child .usa-input { - &:first-child { - margin-top: 0; - } - } - } - - @include media($medium-screen) { - @include grid-row; - align-items: flex-start; - - .form-col { - .usa-input { - margin-left: ($gap * 4); - margin-right: ($gap * 4); - } - - &:first-child { - .usa-input { - margin-left: 0; - } - } - - &:last-child { - .usa-input { - margin-right: 0; - } - } - } - } -} diff --git a/static/styles/elements/_labels.scss b/static/styles/elements/_labels.scss deleted file mode 100644 index 104894e4..00000000 --- a/static/styles/elements/_labels.scss +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Labels - * @see https://designsystem.digital.gov/components/labels/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_labels.scss - */ - -.label { - @include h5; - display: inline-block; - height: 2.4rem; - line-height: 2.4rem; - color: $color-white; - background-color: $color-gray; - vertical-align: middle; - margin: 0 $gap; - padding: 0 $gap; - border-radius: $gap / 2; - - &.label--info { - background-color: $color-primary; - } - - &.label--warning { - background-color: $color-gold; - } - - &.label--error { - background-color: $color-red; - } - - &.label--success { - background-color: $color-green; - } -} diff --git a/static/styles/elements/_panels.scss b/static/styles/elements/_panels.scss deleted file mode 100644 index af5decf4..00000000 --- a/static/styles/elements/_panels.scss +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Panels - * A generic block container - */ - - @mixin panel-base { - background-color: $color-white; - border-top-width: 1px; - border-bottom-width: 1px; - border-top-style: solid; - border-bottom-style: solid; - border-left: 0; - border-right: 0; -} - -@mixin panel-theme-default { - border-top-color: $color-black; - border-bottom-color: $color-gray-light; -} - -@mixin panel-margin { - margin-top: 0; - margin-left: 0; - margin-right: 0; - margin-bottom: $site-margins-mobile * 2; - - @include media($medium-screen) { - margin-bottom: $site-margins * 2; - } -} - -@mixin panel-actions { - padding: $gap; -} - -.panel { - @include panel-base; - @include panel-theme-default; - @include panel-margin; - - .panel__content { - margin: ($gap * 2) 0; - padding: 0 ($gap * 2); - - @include media($medium-screen) { - margin: ($gap * 4) 0; - padding: 0 ($gap * 4); - } - } - - .panel__heading { - margin: $gap * 2; - - @include media($medium-screen) { - margin: $gap * 4; - } - - h1, h2, h3, h4, h5, h6 { - margin: 0; - } - } -} - -.panel__actions { - @include panel-actions; -} - diff --git a/static/styles/elements/_sidenav.scss b/static/styles/elements/_sidenav.scss deleted file mode 100644 index d4c67366..00000000 --- a/static/styles/elements/_sidenav.scss +++ /dev/null @@ -1,87 +0,0 @@ -.sidenav { - ul { - list-style: none; - margin: 0; - padding: 0; - - li { - margin: 0; - display: block; - } - } - - .sidenav__link { - display: block; - border-top: 1px solid $color-black; - padding: $gap ($gap * 2); - color: $color-black; - text-decoration: none; - white-space: nowrap; - - .sidenav__link-icon { - margin-left: - ($gap * .5); - } - - &.sidenav__link--disabled { - color: $color-shadow; - pointer-events: none; - } - - &.sidenav__link--active { - @include h4; - background-color: $color-white; - color: $color-primary; - box-shadow: inset ($gap / 2) 0 0 0 $color-primary; - - .sidenav__link-icon { - @include icon-style-active; - } - - + ul { - background-color: $color-white; - - .sidenav__link { - &--active { - @include h5; - color: $color-primary; - box-shadow: none; - } - } - } - } - - + ul { - padding-bottom: $gap / 2; - - li { - .sidenav__link { - @include h5; - 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; - } - } - } - } - - &:hover { - color: $color-primary; - - .sidenav__link-icon { - @include icon-style-active; - } - - } - } -} diff --git a/static/styles/elements/_tables.scss b/static/styles/elements/_tables.scss deleted file mode 100644 index e1602dfd..00000000 --- a/static/styles/elements/_tables.scss +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Tables - * @see https://designsystem.digital.gov/components/tables/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_table.scss - */ - - table { - @include panel-margin; - min-width: 100%; - - tbody { - tr { - th, - td { - @include block-list-item; - display: table-cell; - white-space: nowrap; - border-bottom-style: dashed; - border-top: none; - - &:last-child { - border-bottom-style: dashed; - } - } - - &:last-child { - td, - th { - border-bottom-style: solid; - } - } - - .table-cell--align-right { - text-align: right; - } - - .table-cell--shrink { - width: 1%; - } - - .table-cell--expand { - width: 100%; - } - - .table-cell--hide-small { - display: none; - - @include media($medium-screen) { - display: table-cell; - } - } - } - } - - thead { - tr { - th { - @include block-list-header; - display: table-cell; - } - } - } - - @at-root .panel #{&} { - tr:last-child td { - border-bottom: 0; - } - - &:last-child { - margin-bottom: 0; - } - } -} - -.responsive-table-wrapper { - overflow-x: auto; - @include panel-margin; - - table { - margin-bottom: 0; - } - - @at-root .panel #{&} { - tr:last-child td { - border-bottom: 0; - } - - &:last-child { - margin-bottom: 0; - } - } -} diff --git a/static/styles/elements/_typography.scss b/static/styles/elements/_typography.scss deleted file mode 100644 index fcdc97d9..00000000 --- a/static/styles/elements/_typography.scss +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Typography - * @see https://designsystem.digital.gov/components/typography/ - * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_typography.scss - */ - - * { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -p { - margin: 0 0 ($gap * 2) 0; - @include line-max; -} - -h1, h2, h3, h4, h5, h6 { - font-family: $font-sans; - margin: ($gap * 2) 0; - - + .subtitle * { - margin-top: 0; - } - -} - -.h1 { @include h1; } -.h2 { @include h2; } -.h3 { @include h3; } -.h4 { @include h4; } -.h5 { @include h5; } -.h6 { @include h6; } - -a, -a:hover { - transition: - background 0.2s, - border 0.2s, - box-shadow 0.2s, - color 0.2s; -} - -a:visited { - color: $color-blue; -} - -dl { - dt { - display: inline; - font-weight: bold; - } - dd { - -webkit-margin-start: 0; - } - - > div { - margin-bottom: $gap * 2; - } -} \ No newline at end of file diff --git a/static/styles/sections/_login.scss b/static/styles/sections/_login.scss deleted file mode 100644 index 030d09d5..00000000 --- a/static/styles/sections/_login.scss +++ /dev/null @@ -1,3 +0,0 @@ -.login-area { - text-align: center; -} \ No newline at end of file diff --git a/static/styles/sections/_member_edit.scss b/static/styles/sections/_member_edit.scss deleted file mode 100644 index aef2e042..00000000 --- a/static/styles/sections/_member_edit.scss +++ /dev/null @@ -1,41 +0,0 @@ -.member-card { - @include grid-row; - padding: $gap*2; - justify-content: space-between; - - dl { - margin: 0; - - > div { - margin-bottom: $gap; - } - } - - dt { - font-weight: normal; - color: $color-gray; - } - - dd { - display: inline; - } - - .member-card__header { - display: flex; - flex-direction: column; - justify-content: space-between; - } - - .member-card__heading { - margin: 0; - @include h2; - } - - .member-card__details { - text-align: right; - - .icon-link { - margin: 0 -$gap; - } - } -} \ No newline at end of file diff --git a/static/styles/sections/_project_edit.scss b/static/styles/sections/_project_edit.scss deleted file mode 100644 index 2222fd26..00000000 --- a/static/styles/sections/_project_edit.scss +++ /dev/null @@ -1,19 +0,0 @@ -.project-edit__env-list-item { - display: flex; - flex-direction: row; - align-items: flex-end; - - .usa-input { - margin: 0 ($gap * 4) 0 0; - flex-grow: 1; - } - - .project-edit__env-list-item__remover { - @include icon-link; - @include icon-link-vertical; - @include icon-link-color($color-red, $color-red-lightest); - - margin-bottom: -$gap; - margin-right: -$gap; - } -} diff --git a/static/styles/sections/_projects_list.scss b/static/styles/sections/_projects_list.scss deleted file mode 100644 index fe62b7a6..00000000 --- a/static/styles/sections/_projects_list.scss +++ /dev/null @@ -1,22 +0,0 @@ -.project-list-item { - .project-list-item__environment { - display: flex; - flex-direction: row; - justify-content: space-between; - - .project-list-item__environment__link { - @include icon-link; - @include icon-link-large; - } - - .project-list-item__environment__members { - display: flex; - flex-direction: row; - align-items: center; - - span { - @include h6; - } - } - } -} diff --git a/static/styles/sections/_request_approval.scss b/static/styles/sections/_request_approval.scss deleted file mode 100644 index 5769d5d9..00000000 --- a/static/styles/sections/_request_approval.scss +++ /dev/null @@ -1,97 +0,0 @@ -.request-approval { - .request-approval__heading { - display: flex; - flex-direction: row; - align-items: center; - } - - .request-approval__info-columns { - flex-wrap: wrap; - - .col { - flex-basis: 100%; - - @include media($medium-screen) { - flex-basis: 50%; - - &:first-child { - padding-right: $gap * 2; - } - &:last-child { - padding-left: $gap * 2; - } - } - } - } - - .request-approval__columns__heading { - &:first-child { - @include media($medium-screen) { - margin-top: 0; - } - } - } - - .approval-log { - ol { - list-style: none; - margin: 0; - padding: 0; - - li { - padding: $gap * 2; - border-top: 1px dashed $color-gray-light; - - &:first-child { - border-top-style: solid; - } - - @include media($medium-screen) { - padding: $gap * 4; - } - } - } - .approval-log__log-item { - display: flex; - flex-direction: column-reverse; - justify-content: flex-end; - - @include media($medium-screen) { - flex-direction: row-reverse; - } - - .approval-log__log-item__header { - @include h4; - margin: 0 0 $gap 0; - } - - .approval-log__log-item__timestamp { - @include h5; - margin-right: $gap * 2; - color: $color-gray; - flex-grow: 0; - - @include media($large-screen) { - margin-right: $gap * 4; - } - } - - .approval-log__behalfs { - display: flex; - flex-direction: row; - - .approval-log__behalf { - margin-right: $gap * 2; - - @include media($medium-screen) { - margin-right: $gap * 4; - } - - span { - display: block; - } - } - } - } - } -} From c468b018552b4eb8f91581c1b5be041d163a0811 Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 3 Aug 2018 09:50:24 -0400 Subject: [PATCH 110/173] have test script to reset test database --- script/include | 2 +- script/test | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/script/include b/script/include index 90a453b2..05492977 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 90a453b2ac4272961b3ed5f7d77d60816a09e092 +Subproject commit 05492977844309215c122e925159f9f8c62014e3 diff --git a/script/test b/script/test index ceb1c5c2..8759a347 100755 --- a/script/test +++ b/script/test @@ -6,6 +6,12 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh export FLASK_ENV=test +# Set database name +DATABASE_NAME="atat_test" + +# Enable database resetting +RESET_DB="true" + # Define all relevant python files and directories for this app PYTHON_FILES="./app.py ./atst ./config" From 2a3e62e66ee8363ce8fa907ba1bc5dbdd89ed4b7 Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 3 Aug 2018 09:50:39 -0400 Subject: [PATCH 111/173] CI should use the test database --- config/ci.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/config/ci.ini b/config/ci.ini index 3796c0a7..64c8ac1f 100644 --- a/config/ci.ini +++ b/config/ci.ini @@ -1,2 +1,3 @@ [default] PGHOST = postgreshost +PGDATABASE = atat_test From 51161dce3d6b0ea4fcaf672ac787af6855ba44d9 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Fri, 3 Aug 2018 10:32:53 -0400 Subject: [PATCH 112/173] Resolve conflicts in pipfile.lock after adding flask-wtf back --- Pipfile.lock | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index ead0c686..2a25ba15 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9f17530cb96833c424369b9cac305cb43a817cdf19605aaedeb2d98566302857" + "sha256": "0738d50fa0153e356ddd9ce23bcc781914ed0fe860044457a9db9fc0e1cff46b" }, "pipfile-spec": 6, "requires": { @@ -62,6 +62,14 @@ "index": "pypi", "version": "==2.3.2" }, + "flask-wtf": { + "hashes": [ + "sha256:5d14d55cfd35f613d99ee7cba0fc3fbbe63ba02f544d349158c14ca15561cc36", + "sha256:d9a9e366b32dcbb98ef17228e76be15702cd2600675668bca23f63a7947fd5ac" + ], + "index": "pypi", + "version": "==0.14.2" + }, "itsdangerous": { "hashes": [ "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" @@ -160,6 +168,7 @@ "sha256:1d936da41ee06216d89fdc7ead1ee9a5da2811a8787515a976b646e110c3f622", "sha256:e4ef42e82b0b493c5849eed98b5ab49d6767caf982127e9a33167f1153b36cc5" ], + "markers": "python_version != '3.2.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7'", "version": "==2018.5" }, "redis": { @@ -393,6 +402,7 @@ "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" ], + "markers": "python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.0.*'", "version": "==4.3.4" }, "itsdangerous": { @@ -510,6 +520,7 @@ "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], + "markers": "python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.0.*'", "version": "==0.7.1" }, "prompt-toolkit": { @@ -532,6 +543,7 @@ "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], + "markers": "python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.0.*'", "version": "==1.5.4" }, "pygments": { @@ -551,11 +563,11 @@ }, "pytest": { "hashes": [ - "sha256:8214ab8446104a1d0c17fbd218ec6aac743236c6ffbe23abc038e40213c60b88", - "sha256:e2b2c6e1560b8f9dc8dd600b0923183fbd68ba3d9bdecde04467be6dd296a384" + "sha256:86a8dbf407e437351cef4dba46736e9c5a6e3c3ac71b2e942209748e76ff2086", + "sha256:e74466e97ac14582a8188ff4c53e6cc3810315f342f6096899332ae864c1d432" ], "index": "pypi", - "version": "==3.7.0" + "version": "==3.7.1" }, "pytest-flask": { "hashes": [ @@ -581,15 +593,11 @@ }, "pyyaml": { "hashes": [ - "sha256:1cbc199009e78f92d9edf554be4fe40fb7b0bef71ba688602a00e97a51909110", "sha256:254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb", "sha256:3108529b78577327d15eec243f0ff348a0640b0c3478d67ad7f5648f93bac3e2", "sha256:3c17fb92c8ba2f525e4b5f7941d850e7a48c3a59b32d331e2502a3cdc6648e76", - "sha256:6f89b5c95e93945b597776163403d47af72d243f366bf4622ff08bdfd1c950b7", "sha256:8d6d96001aa7f0a6a4a95e8143225b5d06e41b1131044913fecb8f85a125714b", - "sha256:be622cc81696e24d0836ba71f6272a2b5767669b0d79fdcf0295d51ac2e156c8", - "sha256:c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b", - "sha256:f39411e380e2182ad33be039e8ee5770a5d9efe01a2bfb7ae58d9ba31c4a2a9d" + "sha256:c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b" ], "version": "==4.2b4" }, From a0082a2ae255203e7887133d7142619b3f319ace Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Fri, 3 Aug 2018 10:34:24 -0400 Subject: [PATCH 113/173] Revert "CI should use the test database" CI needs to use the regular databse during setup and should use the test database when running tests only This reverts commit 9bc64ba269c99ab6da24dca475d0d5ff22c9474d. --- config/ci.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/config/ci.ini b/config/ci.ini index 64c8ac1f..3796c0a7 100644 --- a/config/ci.ini +++ b/config/ci.ini @@ -1,3 +1,2 @@ [default] PGHOST = postgreshost -PGDATABASE = atat_test From 64b40c0cf38781a38e46c2674b3c5f58882e9f51 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 3 Aug 2018 10:35:04 -0400 Subject: [PATCH 114/173] Reorganize macros into separate component files Replace a few old UI Module instances with macros --- templates/components.html | 145 ------------------ templates/components/alert.html | 39 +++++ templates/components/alert.html.to | 35 ----- templates/components/empty_state.html | 13 ++ templates/components/empty_state.html.to | 9 -- templates/components/icon.html | 6 + templates/components/icon.html.to | 2 - templates/components/modal.html | 9 ++ templates/components/modal.html.to | 7 - templates/components/options_input.html | 27 ++++ templates/components/options_input.html.to | 25 --- templates/components/sidenav_item.html | 28 ++++ templates/components/text_input.html | 23 +++ templates/components/text_input.html.to | 21 --- templates/member_edit.html.to | 7 +- templates/navigation/_sidenav_item.html.to | 24 --- templates/navigation/global_navigation.html | 3 +- templates/navigation/topbar.html | 3 +- .../navigation/workspace_navigation.html.to | 32 ++-- templates/project_edit.html.to | 6 +- templates/requests.html | 4 +- templates/requests/screen-1.html | 4 +- templates/requests/screen-2.html | 4 +- templates/requests/screen-3.html | 3 +- templates/requests/screen-4.html | 3 +- templates/requests/screen-5.html | 2 + templates/styleguide.html | 4 +- templates/workspace_members.html | 6 +- templates/workspace_projects.html | 2 +- 29 files changed, 198 insertions(+), 298 deletions(-) delete mode 100644 templates/components.html create mode 100644 templates/components/alert.html delete mode 100644 templates/components/alert.html.to create mode 100644 templates/components/empty_state.html delete mode 100644 templates/components/empty_state.html.to create mode 100644 templates/components/icon.html delete mode 100644 templates/components/icon.html.to create mode 100644 templates/components/modal.html delete mode 100644 templates/components/modal.html.to create mode 100644 templates/components/options_input.html delete mode 100644 templates/components/options_input.html.to create mode 100644 templates/components/sidenav_item.html create mode 100644 templates/components/text_input.html delete mode 100644 templates/components/text_input.html.to delete mode 100644 templates/navigation/_sidenav_item.html.to diff --git a/templates/components.html b/templates/components.html deleted file mode 100644 index a9b566cd..00000000 --- a/templates/components.html +++ /dev/null @@ -1,145 +0,0 @@ -{% macro Icon(name, classes="") -%} - {% autoescape false %} - - {% endautoescape %} -{%- endmacro %} - -{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} -
  • - - {% if icon %} - {{ Icon(icon, classes="sidenav__link-icon") }} - {% endif %} - - {{label}} - - - {% if subnav and active %} - - {% endif %} -
  • -{%- endmacro %} - -{% macro Modal() -%} - -{%- endmacro %} - -{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%} -
    -

    {{ message }}

    - - {% if icon %} - {{ Icon(icon) }} - {% endif %} - - {{ actionLabel }} -
    -{%- endmacro %} - -{% macro Alert(title, message=None, actions=None, level='info') -%} -{% set role = 'alertdialog' if actions else 'alert' %} -{% set levels = { - 'warning': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'error': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'info': { - 'icon': 'info', - 'tone': 'polite' - }, - 'success': { - 'icon': 'ok', - 'tone': 'polite' - } -} %} - -
    - {{ Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') }} - -
    -

    {{title}}

    - - {% if message %} -
    {{ message | safe }}
    - {% endif %} - - {% if actions %} -
    {{ actions | safe }}
    - {% endif %} -
    -
    -{%- endmacro %} - -{% macro TextInput(field, placeholder='') -%} -
    - - - {{ field(placeholder=placeholder) | safe }} - - {% if field.errors %} - {% for error in field.errors %} - {{ error }} - {% endfor %} - {% endif %} -
    -{%- endmacro %} - -{% macro OptionsInput(field, inline=False) -%} -
    - -
    - - {{ field.label }} - - {% if field.description %} - {{ field.description | safe }} - {% endif %} - - {% if field.errors %} - {{ Icon('alert') }} - {% endif %} - - - {{ field() }} - - {% if field.errors %} - {% for error in field.errors %} - {{ error }} - {% endfor %} - {% endif %} - -
    -
    - -{%- endmacro %} diff --git a/templates/components/alert.html b/templates/components/alert.html new file mode 100644 index 00000000..d3385d1d --- /dev/null +++ b/templates/components/alert.html @@ -0,0 +1,39 @@ +{% from "components/icon.html" import Icon %} + +{% macro Alert(title, message=None, actions=None, level='info') -%} + {% set role = 'alertdialog' if actions else 'alert' %} + {% set levels = { + 'warning': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'error': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'info': { + 'icon': 'info', + 'tone': 'polite' + }, + 'success': { + 'icon': 'ok', + 'tone': 'polite' + } + } %} + +
    + {{ Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') }} + +
    +

    {{title}}

    + + {% if message %} +
    {{ message | safe }}
    + {% endif %} + + {% if actions %} +
    {{ actions | safe }}
    + {% endif %} +
    +
    +{%- endmacro %} diff --git a/templates/components/alert.html.to b/templates/components/alert.html.to deleted file mode 100644 index 05cac613..00000000 --- a/templates/components/alert.html.to +++ /dev/null @@ -1,35 +0,0 @@ -{% set role = 'alertdialog' if actions else 'alert' %} -{% set levels = { - 'warning': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'error': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'info': { - 'icon': 'info', - 'tone': 'polite' - }, - 'success': { - 'icon': 'ok', - 'tone': 'polite' - } -} %} - -
    - {% module Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') %} - -
    -

    {{title}}

    - - {% if message %} -
    {% raw message %}
    - {% end %} - - {% if actions %} -
    {% raw actions %}
    - {% end %} -
    -
    diff --git a/templates/components/empty_state.html b/templates/components/empty_state.html new file mode 100644 index 00000000..7dc6f119 --- /dev/null +++ b/templates/components/empty_state.html @@ -0,0 +1,13 @@ +{% from "components/icon.html" import Icon %} + +{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%} +
    +

    {{ message }}

    + + {% if icon %} + {{ Icon(icon) }} + {% endif %} + + {{ actionLabel }} +
    +{%- endmacro %} diff --git a/templates/components/empty_state.html.to b/templates/components/empty_state.html.to deleted file mode 100644 index 30246ddb..00000000 --- a/templates/components/empty_state.html.to +++ /dev/null @@ -1,9 +0,0 @@ -
    -

    {{ message }}

    - - {% if icon %} - {% module Icon(icon) %} - {% end %} - - {{ actionLabel }} -
    diff --git a/templates/components/icon.html b/templates/components/icon.html new file mode 100644 index 00000000..42139e57 --- /dev/null +++ b/templates/components/icon.html @@ -0,0 +1,6 @@ +{% macro Icon(name, classes="") -%} + {% autoescape false %} + + {% endautoescape %} +{%- endmacro %} + diff --git a/templates/components/icon.html.to b/templates/components/icon.html.to deleted file mode 100644 index 99e74b40..00000000 --- a/templates/components/icon.html.to +++ /dev/null @@ -1,2 +0,0 @@ -{% autoescape None %} - diff --git a/templates/components/modal.html b/templates/components/modal.html new file mode 100644 index 00000000..8e483de4 --- /dev/null +++ b/templates/components/modal.html @@ -0,0 +1,9 @@ +{% macro Modal() -%} + +{%- endmacro %} diff --git a/templates/components/modal.html.to b/templates/components/modal.html.to deleted file mode 100644 index 4330adbd..00000000 --- a/templates/components/modal.html.to +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/templates/components/options_input.html b/templates/components/options_input.html new file mode 100644 index 00000000..55342c24 --- /dev/null +++ b/templates/components/options_input.html @@ -0,0 +1,27 @@ +{% macro OptionsInput(field, inline=False) -%} +
    + +
    + + {{ field.label }} + + {% if field.description %} + {{ field.description | safe }} + {% endif %} + + {% if field.errors %} + {{ Icon('alert') }} + {% endif %} + + + {{ field() }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} + +
    +
    +{%- endmacro %} diff --git a/templates/components/options_input.html.to b/templates/components/options_input.html.to deleted file mode 100644 index 8a15e041..00000000 --- a/templates/components/options_input.html.to +++ /dev/null @@ -1,25 +0,0 @@ -
    - -
    - - {{ label }} - - {% if description %} - {% raw description %} - {% end %} - - {% if errors %} - {% module Icon('alert') %} - {% end %} - - - {% raw field() %} - - {% if errors %} - {% for error in errors %} - {{ error }} - {% end %} - {% end %} - -
    -
    diff --git a/templates/components/sidenav_item.html b/templates/components/sidenav_item.html new file mode 100644 index 00000000..64f5b765 --- /dev/null +++ b/templates/components/sidenav_item.html @@ -0,0 +1,28 @@ +{% from "components/icon.html" import Icon %} + +{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} +
  • + + {% if icon %} + {{ Icon(icon, classes="sidenav__link-icon") }} + {% endif %} + + {{label}} + + + {% if subnav and active %} + + {% endif %} +
  • +{%- endmacro %} diff --git a/templates/components/text_input.html b/templates/components/text_input.html new file mode 100644 index 00000000..0f50ca89 --- /dev/null +++ b/templates/components/text_input.html @@ -0,0 +1,23 @@ +{% macro TextInput(field, placeholder='') -%} +
    + + + {{ field(placeholder=placeholder) | safe }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} +
    +{%- endmacro %} diff --git a/templates/components/text_input.html.to b/templates/components/text_input.html.to deleted file mode 100644 index 2a800abc..00000000 --- a/templates/components/text_input.html.to +++ /dev/null @@ -1,21 +0,0 @@ -
    - - - {% raw field(placeholder=placeholder) %} - - {% if errors %} - {% for error in errors %} - {{ error }} - {% end %} - {% end %} -
    diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index d454152c..fbe92f35 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -1,5 +1,7 @@ {% extends "base_workspace.html.to" %} +{% from "components/alert.html" import Alert %} + {% block template_vars %} {% set is_new_member = False %} {% set member_name = "Danny Knight" %} @@ -10,11 +12,12 @@ {% block workspace_content %} -{% module Alert( +{{ Alert( "UI Mock", message="

    Please note, this screen is a non-functional UI mockup.

    ", level="info" - ) %} + ) +}}
    diff --git a/templates/navigation/_sidenav_item.html.to b/templates/navigation/_sidenav_item.html.to deleted file mode 100644 index 888245bc..00000000 --- a/templates/navigation/_sidenav_item.html.to +++ /dev/null @@ -1,24 +0,0 @@ -
  • - - {% if icon %} - {% module Icon(icon, classes="sidenav__link-icon") %} - {% end %} - - {{label}} - - - {% if subnav and active %} - - {% end %} -
  • diff --git a/templates/navigation/global_navigation.html b/templates/navigation/global_navigation.html index 594bf574..79728185 100644 --- a/templates/navigation/global_navigation.html +++ b/templates/navigation/global_navigation.html @@ -1,4 +1,5 @@ -{% from "components.html" import SidenavItem %} +{% from "components/sidenav_item.html" import SidenavItem %} +