Compare commits

...

456 Commits

Author SHA1 Message Date
Carlo Costino
de0aed60f9 Merge pull request #1375 from GSA/1373-bug-single-job---preview-does-not-display-variable-information
Bug: Single Job - Preview does not display variable information
2024-04-08 17:44:59 -04:00
Carlo Costino
84bef51d7d Merge pull request #1400 from GSA/update-utils-0-4-5
Update utils to 0.4.5
2024-04-08 12:02:43 -04:00
Carlo Costino
d5d5a45138 Update utils to 0.4.5
This changeset updates notifications-utils to 0.4.5, which includes a few minor fixes and several dependency updates.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-04-08 11:41:39 -04:00
Beverly Nguyen
6acbce0858 removed jobs template 2024-04-05 12:14:56 -07:00
Carlo Costino
2b6b58c93a Merge pull request #1349 from GSA/810-hide-personalization-after-sending
810 hide personalization after sending
2024-04-05 10:59:04 -04:00
Carlo Costino
3e1c06f75c Merge pull request #1386 from GSA/login_gov_env_vars
fix login.gov stuff in sample.env
2024-04-05 09:44:23 -04:00
Carlo Costino
2ede41ce6a Merge pull request #1347 from GSA/1260-dashboard-step-15-use-full-width-base-template-for-landing-page
move footer and head to base.html
2024-04-04 17:13:59 -04:00
Kenneth Kehl
40efb4b561 fix login.gov stuff in sample.env 2024-04-04 13:34:40 -07:00
Beverly Nguyen
51845ec0b0 delete notes 2024-04-04 13:23:21 -07:00
Beverly Nguyen
2075400342 merge main 2024-04-04 13:00:03 -07:00
Steven Reilly
11b970adf8 Merge pull request #1385 from GSA/update-gh-actions
Update GitHub Actions
2024-04-04 09:20:38 -04:00
Carlo Costino
14508b2d97 Update GitHub Actions
This changeset updates all references to GitHub Actions to be version 4 due to a mandatory Node.js update.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-04-04 08:40:24 -04:00
Carlo Costino
1f4573628f Merge pull request #1379 from GSA/login_gov_state
change state to something non-arbitrary
2024-04-03 19:13:40 -04:00
Carlo Costino
2cf3ddb6ff Merge pull request #1371 from GSA/1365-update-date-on-preview-page-and-status-page
Update datetime on preview to be more human readable
2024-04-03 19:12:27 -04:00
Carlo Costino
cc20c02839 Merge pull request #1370 from GSA/1213-clean-up-usage-content
1213 - Removed the Usage page and updated the Dashboard Landing page
2024-04-03 19:10:33 -04:00
Carlo Costino
2d7fba03f5 Merge pull request #1356 from GSA/1252-missing-blue-boxes
1252 missing blue boxes
2024-04-03 19:09:22 -04:00
Carlo Costino
1c0c60a917 Merge pull request #1344 from GSA/1328-base-template-header-component
Converting Header from macro to html
2024-04-03 19:05:02 -04:00
Carlo Costino
6b2ab54870 Merge pull request #1326 from GSA/805-make-dashboard-links-clickable
805 make dashboard links clickable
2024-04-03 19:03:41 -04:00
Carlo Costino
7f54232f21 Merge pull request #1382 from GSA/notify-admin-151
remove template preview stuff
2024-04-03 18:54:03 -04:00
Carlo Costino
8b17adeb34 Merge pull request #1296 from GSA/1215-clean-up-macros-table-on-preview-page
Converting 'preview page' table Macro to HTML
2024-04-03 18:38:31 -04:00
Carlo Costino
c4611a291f Merge pull request #1383 from GSA/dependabot-updates
Update several recent dependencies
2024-04-03 17:52:42 -04:00
Carlo Costino
616957c103 Added an explicit sync of the poetry.lock file to make bootstrap to make sure dependency updates will work
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-04-03 17:31:15 -04:00
Carlo Costino
e411774ada Added a few more minor version bumps
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-04-03 17:24:26 -04:00
Carlo Costino
748dbc12fd Update several recent dependencies
This changeset updates several dependencies that Dependabot has flagged for us but cannot merge due to the E2E test bug with it.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-04-03 17:09:35 -04:00
Kenneth Kehl
9021530a1a remove template preview stuff 2024-04-03 13:38:54 -07:00
Beverly Nguyen
745532e657 added template for personalisation 2024-04-02 16:30:40 -07:00
Beverly Nguyen
32f36d433a updated css to placeholder 2024-04-02 14:11:44 -07:00
Kenneth Kehl
cde0ab018a fix null on some unit tests 2024-04-02 14:02:04 -07:00
Kenneth Kehl
10ed1dab22 fixes 2024-04-02 13:46:47 -07:00
Kenneth Kehl
817c01faff change state to something non-arbitrary 2024-04-02 13:32:32 -07:00
Beverly Nguyen
acdd2806fc added force_hide_sender 2024-04-01 18:03:38 -07:00
Carlo Costino
e572d789e0 Merge pull request #1374 from GSA/debug_staging
remove debug
2024-04-01 16:43:32 -04:00
Kenneth Kehl
e4990cfd70 remove debug 2024-04-01 12:55:37 -07:00
Jonathan Bobel
23903b7d29 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1213-clean-up-usage-content 2024-04-01 11:10:41 -04:00
Carlo Costino
0fa9910e2c Merge pull request #1372 from GSA/debug_staging
Handle new user case
2024-03-29 12:27:42 -04:00
Kenneth Kehl
e5136d9fa7 return None if no user 2024-03-29 07:45:16 -07:00
Beverly Nguyen
a2ab04018d fix imports 2024-03-28 18:05:12 -07:00
Beverly Nguyen
5854176ec8 add prase_dt function 2024-03-28 18:01:42 -07:00
Carlo Costino
3abe3352df Merge pull request #1369 from GSA/debug_staging
handle case where existing user is invited to another service
2024-03-28 17:03:51 -04:00
Kenneth Kehl
f092ad8f98 handle case where existing user is invited to another service 2024-03-28 13:20:22 -07:00
Jonathan Bobel
2c57d0d373 1213 - Removed the Usage page and updated the Dashboard Landing page 2024-03-28 15:58:02 -04:00
Carlo Costino
bc79e4dd2c Merge pull request #1368 from GSA/debug_staging
debug staging
2024-03-28 15:18:45 -04:00
Kenneth Kehl
9b1c9b8ccf ugh 2024-03-28 11:35:25 -07:00
Kenneth Kehl
b29c2a3a62 debug staging 2024-03-28 11:15:10 -07:00
Carlo Costino
245bcaecb3 Merge pull request #1363 from GSA/mitchell-login-gov-doc-update
Reformat nested list in Login.gov documentation
2024-03-28 12:32:51 -04:00
Carlo Costino
2ca4c1b029 Merge branch 'mh-patch-1' into mitchell-login-gov-doc-update
Merging in Login.gov documentation updates from @mitchellhenke - thank
you!
2024-03-28 12:18:24 -04:00
Carlo Costino
faaf602dea Merge branch 'patch-1' of github.com:mitchellhenke/notifications-admin into mh-patch-1
Merging in Login.gov documentation updates from @mitchellhenke - thank
you!
2024-03-28 12:16:47 -04:00
Jonathan Bobel
c6af0957e9 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1252-missing-blue-boxes 2024-03-27 09:57:34 -04:00
Beverly Nguyen
d8e9aaee0f updated header nav and seperated out usabanner 2024-03-26 18:00:01 -07:00
Beverly Nguyen
4b9ec67345 merge main 2024-03-26 13:41:42 -07:00
Jonathan Bobel
6c1090ecb2 1252 - add back blue boxes for pending and delivered 2024-03-26 16:06:13 -04:00
Carlo Costino
fd1ab3bf2e Merge pull request #1212 from GSA/1210-create-confirmation-status-page-the-last-page-in-the-preview-send-flow
Create confirmation status alert (the last page in the preview send flow) #1211
2024-03-26 15:55:11 -04:00
Beverly Nguyen
89e7de0ab6 fixed the testing 2024-03-26 12:37:06 -07:00
Beverly Nguyen
e743ab41ff merge main and fixed conflicts 2024-03-26 10:53:01 -07:00
Carlo Costino
6d1efcadba Merge pull request #1325 from GSA/1283-standardize-the-dates-from-format_datetime_short-to-either-numerical-or-text
Standardizing Datetimes to Numeric and Table Formats
2024-03-26 13:29:13 -04:00
Jonathan Bobel
07ee8dfe1e Updated image 2024-03-26 12:15:56 -04:00
Jonathan Bobel
9d673a4d77 Merge branch 'main' of https://github.com/GSA/notifications-admin into 810-hide-personalization-after-sending 2024-03-26 11:23:52 -04:00
Jonathan Bobel
8ca32f476c 810 - Content updates to link area in Send Message flow 2024-03-26 11:23:39 -04:00
Carlo Costino
0e0ee8ae0c Merge pull request #1341 from GSA/notify-admin-1304
Add error handling for successful Login.gov authentications without a…
2024-03-26 11:07:52 -04:00
Mitchell Henke
4428df7dd5 Reformat nested list 2024-03-26 15:06:26 +00:00
Carlo Costino
9beb0a732c Merge pull request #1310 from GSA/1250-login-gov-add-new-user
1250 - Login.gov - New User flow
2024-03-26 10:53:40 -04:00
Beverly Nguyen
39c19594cd updated testing 2024-03-25 15:56:33 -07:00
Beverly Nguyen
4af4fecd45 revert extends 2024-03-25 15:32:27 -07:00
Beverly Nguyen
05563a7051 moved footer and head to base.html 2024-03-25 15:26:12 -07:00
Jonathan Bobel
6e64df0c0b Content update 2024-03-25 15:07:29 -04:00
Jonathan Bobel
e24f77ec63 810 - Changed the link text on this page and also had to update the image for the Security page 2024-03-25 15:07:20 -04:00
Carlo Costino
db5c259818 Merge pull request #1333 from GSA/1293-bug-team-members-with-long-names
Edited style sheet to wrap long emails that overflow the parent div
2024-03-25 12:43:44 -04:00
Steven Reilly
bf4f134538 Merge pull request #1345 from GSA/adjust-e2e-test-fixtures
Adjust E2E test fixtures
2024-03-25 12:38:14 -04:00
Carlo Costino
1aa2501d1d Adjust E2E test fixtures
This changeset adjusts the scope of the end-to-end (E2E) test fixtures so that they behave as intended and we have truly isolated tests.  We may adjust these again in the future depending on our needs, but for right now this will hopefully keep things simple for us as we start to build out an E2E test library.

Thank you, @terrazoon, for flagging this!

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-25 12:08:34 -04:00
Kenneth Kehl
addc078cbe merge from main 2024-03-22 11:57:47 -07:00
Kenneth Kehl
8362c6b975 fix invites for service and organization 2024-03-22 11:08:49 -07:00
Beverly Nguyen
7c179cadca header marco to html 2024-03-21 21:03:32 -07:00
Carlo Costino
c83655c48c Merge pull request #1342 from GSA/fix-python-deploy
Update Cloud Foundry runtime.txt file
2024-03-21 17:54:15 -04:00
Carlo Costino
c4d738d70b Update Cloud Foundry runtime.txt file
This changeset updates the runtime.txt file so that Cloud Foundry picks up Python 3.12.x instead of Python 3.9.x

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-21 17:45:01 -04:00
Carlo Costino
a1736b5a4d Merge pull request #1284 from GSA/notify-admin-818
updates with python upgrade
2024-03-21 17:26:04 -04:00
samathad2023
b006e2cacf utils dependencies updates 2024-03-21 13:01:14 -07:00
Carlo Costino
8e75110892 Merge pull request #1294 from GSA/1258-base-template-head
1258 updated base template <head>
2024-03-21 15:51:45 -04:00
Kenneth Kehl
099345fe1e Add error handling for successful Login.gov authentications without a Notify account 2024-03-21 10:58:36 -07:00
Jonathan Bobel
8afacfa89b Moved the <head> and removed the comment for base.html 2024-03-21 12:48:36 -04:00
Jonathan Bobel
ccd3e44eb1 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1258-base-template-head 2024-03-21 12:42:38 -04:00
Kenneth Kehl
6efb16120d Add error handling for successful Login.gov authentications without a Notify account 2024-03-21 09:34:55 -07:00
Jonathan Bobel
24a0dd8c3b Few style updates per PR feedback 2024-03-21 11:00:44 -04:00
samathad2023
00f81a74fd latest utils commit and sync with main 2024-03-20 14:11:16 -07:00
Anastasia Gradova
c7821f2f73 Edited style to wrap long emails that overflow the
parent div.
2024-03-20 09:13:32 -06:00
Kenneth Kehl
04eaec6dd6 fix register 2024-03-19 14:36:43 -07:00
Kenneth Kehl
b12e638592 fix registration 2024-03-19 14:34:41 -07:00
Kenneth Kehl
c053cc7402 change timezone to hidden field with default for now 2024-03-19 13:30:50 -07:00
Carlo Costino
e1611eebec Merge pull request #1327 from GSA/fix-git-hash-deploy
Add missing env var from cf push
2024-03-19 16:01:28 -04:00
Carlo Costino
4b1db40cbd Fix failing tests
This includes a fix for the commit hash test, which was not referencing the Flask app in a valid way.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-19 15:53:38 -04:00
Kenneth Kehl
197ef11075 fix tests 2024-03-19 11:32:36 -07:00
Carlo Costino
b4986e4170 Enable Login.gov for all environments
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-19 13:59:30 -04:00
Carlo Costino
eb599344ad Add missing env var from cf push
This changeset adds a missing environment variable in the cf push command for the production and demo deployments.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-19 13:38:34 -04:00
Kenneth Kehl
57fa8dad5d revert change to bypass signin page 2024-03-19 10:15:11 -07:00
Kenneth Kehl
4e6f143675 fix register from join service 2024-03-19 09:30:20 -07:00
Jonathan Bobel
27448d90a0 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1258-base-template-head 2024-03-19 12:29:17 -04:00
samathad2023
da5da1abe9 README updates 2024-03-19 09:19:26 -07:00
Jonathan Bobel
de003a8722 Removed "failure" area so the user can get to all the statuses from the Dashboard Landing screen. A better way to view all statuses will come with a Dashboard redesign. 2024-03-19 12:10:43 -04:00
Jonathan Bobel
f391b5af2c Merge branch 'main' of https://github.com/GSA/notifications-admin into 805-make-dashboard-links-clickable 2024-03-19 10:10:14 -04:00
Beverly Nguyen
e9b9072ae6 updated datetimes based on style guide 2024-03-18 15:10:26 -07:00
Beverly Nguyen
077b28bb15 Merge branch 'main' into 1210-create-confirmation-status-page-the-last-page-in-the-preview-send-flow 2024-03-18 14:33:23 -07:00
Beverly Nguyen
10c9b86547 updating datetimes to match styleguides 2024-03-18 14:32:32 -07:00
Jonathan Bobel
05495f4d42 Updating the route 2024-03-18 13:50:23 -04:00
Jonathan Bobel
ee1c4efb03 805 - Making the clickable area on dashboard a button 2024-03-18 12:43:56 -04:00
Beverly Nguyen
bc71549d12 added a conditional to limit only 5 rows to display 2024-03-15 10:33:39 -07:00
Carlo Costino
6b31e5fba0 Merge pull request #1320 from GSA/1319-bug-js-broken-on-non-sign-in-pages
1319 - BUG - adjusting the js to only run when the targeted DOM element exists
2024-03-15 13:25:04 -04:00
Carlo Costino
88c7f9590f Removing extraneous space 2024-03-15 13:07:50 -04:00
Carlo Costino
dea7f28d5a Merge pull request #1322 from GSA/1321-bug-create-login-gov-button-doesnt-work
1321 - Updated link on the sign-in page
2024-03-15 13:05:40 -04:00
Jonathan Bobel
0e608599c3 1321 - Updated link on the sign-in page 2024-03-15 11:41:30 -04:00
Jonathan Bobel
be2dc9a165 1319 - BUG - adjusting the js to only run when the targeted DOM element exists 2024-03-15 10:42:20 -04:00
Carlo Costino
58a1d8e0c4 Merge pull request #1312 from GSA/update-recent-deps
Update Dependabot flagged dependencies
2024-03-14 18:34:50 -04:00
Beverly Nguyen
02ee1a81d1 Merge branch 'main' into 1210-create-confirmation-status-page-the-last-page-in-the-preview-send-flow 2024-03-14 15:07:20 -07:00
Carlo Costino
c43ed20c9e Update Dependabot flagged dependencies
This changeset updates a handful of dependencies that Dependabot has flagged but is not able to test successfully due to a bug with the E2E configuration.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-14 17:31:27 -04:00
Carlo Costino
18be5861d5 Merge pull request #1307 from GSA/notify-admin-1254
hide csv reports in job view if no data available (notify-admin-1254)
2024-03-14 17:28:53 -04:00
Carlo Costino
2afaca6ff1 Merge pull request #1281 from GSA/1266-updated-notify-logo
1266 updated notify logo
2024-03-14 17:17:34 -04:00
Carlo Costino
f0eebfc4f2 Merge pull request #1268 from GSA/1216-login-gov-pre-sign-in-page
1216 login gov pre sign in page
2024-03-14 17:04:25 -04:00
Carlo Costino
cd06337574 Merge pull request #1278 from GSA/1259-base-template-footer
Base template: <footer> #1259
2024-03-14 16:54:44 -04:00
Carlo Costino
85215f45a8 Merge pull request #1311 from GSA/fix_commit_hash
Fix commit hash
2024-03-14 16:36:10 -04:00
Kenneth Kehl
e4087ca9d5 fix commit hash 2024-03-14 13:26:05 -07:00
Kenneth Kehl
3aacdcb3ef fix_commit_hash 2024-03-14 13:25:02 -07:00
Carlo Costino
a09e813f80 Merge pull request #1309 from GSA/update-utils-0-3-0
Update utils to 0.3.0
2024-03-14 16:17:15 -04:00
Carlo Costino
476ba798fc This changeset updates notifications_utils to 0.3.0 to account for other dependency updates.
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-03-14 15:18:40 -04:00
Jonathan Bobel
ef53fe7e09 Adding a hint area if needed, removing test code 2024-03-14 14:37:37 -04:00
Beverly Nguyen
a05e09d345 fixed testing 2024-03-14 11:02:02 -07:00
Jonathan Bobel
04f76cd817 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1250-login-gov-add-new-user 2024-03-14 13:18:39 -04:00
Carlo Costino
b2b6b4f612 Merge pull request #1306 from GSA/add-sim-numbers-totrial
Add simulated numbers to allow list in trial mode
2024-03-14 12:51:19 -04:00
Jonathan Bobel
d67923dafc Added the "set up your profile" page and added a select component 2024-03-14 12:26:12 -04:00
Andrew Shumway
69fce499c3 Merge branch 'main' of https://github.com/GSA/notifications-admin into add-sim-numbers-totrial 2024-03-14 10:17:07 -06:00
Andrew Shumway
119b7fc832 Specify username with fail/success 2024-03-14 10:16:56 -06:00
Carlo Costino
4dc442c4b8 Merge pull request #1245 from GSA/notify-admin-204
Add latest version commit hash to footer (notify-admin-204)
2024-03-14 12:13:19 -04:00
Kenneth Kehl
e35168bd40 hide csv reports in job view if no data available 2024-03-14 08:57:58 -07:00
Andrew Shumway
590a599aa4 Merge branch 'main' of https://github.com/GSA/notifications-admin into add-sim-numbers-totrial 2024-03-13 16:31:48 -06:00
Andrew Shumway
599652256e Add simulated SMS numbers to allow list in trial mode 2024-03-13 16:31:21 -06:00
samathad2023
94e05705f8 Merge remote-tracking branch 'origin' into notify-admin-818 2024-03-13 14:48:19 -07:00
samathad2023
b3998c532e formatting updates 2024-03-13 14:46:34 -07:00
Jonathan Bobel
2717feab7b Using a PNG instead of an SVG for the main logo as it was noted the SVG's font looked pixelated. I also changed the color of the text on the home page as well as its responsive size. 2024-03-13 16:07:39 -04:00
Carlo Costino
ae084617fa Merge pull request #1257 from GSA/974-content-personalization
974 - Content updates on Pricing and Guidance pages
2024-03-13 14:29:26 -04:00
Jonathan Bobel
e1981d3c65 Auto reformat looks like 2024-03-13 13:33:44 -04:00
samathad2023
37f6579ca8 removed comments and updated test-service_settings 2024-03-13 10:28:07 -07:00
Kenneth Kehl
cb0ba15571 merge from main and code review feedback 2024-03-13 10:17:38 -07:00
Jonathan Bobel
6cdc14433b Content updated per PR comments 2024-03-13 11:46:13 -04:00
Jonathan Bobel
8d9c030d90 Merge branch 'main' of https://github.com/GSA/notifications-admin into 974-content-personalization 2024-03-13 10:53:30 -04:00
Jonathan Bobel
45c9018365 Update of head from another issue focusing on the favicon area 2024-03-13 10:51:38 -04:00
Beverly Nguyen
86a6b4ff8e marco to table 2024-03-12 13:41:05 -07:00
Jonathan Bobel
7deaf71463 Updated test 2024-03-12 14:29:16 -04:00
Jonathan Bobel
429a456704 Updating conditional logic 2024-03-12 13:37:44 -04:00
Jonathan Bobel
0ae369d54b Updated the date to April 16th instead of April 9 2024-03-12 13:27:37 -04:00
Jonathan Bobel
46ef759a92 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1216-login-gov-pre-sign-in-page 2024-03-12 13:25:06 -04:00
Jonathan Bobel
ed5902b38e Updates to favicon 2024-03-12 13:23:13 -04:00
Jonathan Bobel
924ff82b03 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1266-updated-notify-logo 2024-03-12 12:45:00 -04:00
Jonathan Bobel
bd7ef33c63 Update to one of the favicon-adjacent files 2024-03-12 12:44:42 -04:00
Jonathan Bobel
f10d854617 1258 - Updated the <head> template 2024-03-12 12:28:30 -04:00
Jonathan Bobel
83d83469e4 Merge branch '1266-updated-notify-logo' of https://github.com/GSA/notifications-admin into 1258-base-template-head 2024-03-11 16:17:31 -04:00
samathad2023
7ff7455022 updated to yml 2024-03-11 11:32:49 -07:00
samathad2023
f0bd88b36a additional comments with test_find_users 2024-03-11 11:24:34 -07:00
samathad2023
f5dbf6ad9e Merge branch 'main' of github.com:GSA/notifications-admin into notify-admin-818 2024-03-11 10:51:04 -07:00
Carlo Costino
e9148851fb Merge pull request #1276 from GSA/notify-admin-1237
Use USWDS error formatting for file too big error (notify-admin-1237)
2024-03-11 12:28:26 -04:00
Carlo Costino
bdea60adb9 Merge pull request #1282 from GSA/notify-admin-1277
update login.gov stuff to use user uuid instead of email (notify-admi…
2024-03-11 11:55:04 -04:00
Carlo Costino
b489f49179 Merge pull request #1184 from GSA/1169-display-confirmation-summary-on-the-preview-page
Create and Display Summary on the Preview page #1169
2024-03-11 09:23:12 -04:00
Beverly Nguyen
d1fe8a2332 updated testing 2024-03-08 16:03:08 -08:00
Beverly Nguyen
7479a6c4ea made changes to the token and removed extra handling errors 2024-03-08 15:05:44 -08:00
samathad2023
c3bb44129c tests and orderedset updates for 3.12 upgrade 2024-03-08 15:00:48 -08:00
Carlo Costino
25c8026d89 Merge pull request #1264 from GSA/1234-dashboard-step-1-create-new-base-template
base.html created
2024-03-08 16:59:53 -05:00
Beverly Nguyen
2822b63a49 Merge branch 'main' into 1169-display-confirmation-summary-on-the-preview-page 2024-03-08 12:34:44 -08:00
Beverly Nguyen
cb3fc0f039 update test 2024-03-08 12:25:09 -08:00
Beverly Nguyen
335b01279b fix sorted imports 2024-03-08 11:54:19 -08:00
Beverly Nguyen
b1b416db8c update datetime naming 2024-03-08 11:43:54 -08:00
Beverly Nguyen
ee5fe38001 update testing 2024-03-08 11:30:49 -08:00
Beverly Nguyen
58a067358e with reivew request 2024-03-08 10:32:29 -08:00
Kenneth Kehl
492f798274 update login.gov stuff to use user uuid instead of email (notify-admin-1277) 2024-03-08 09:04:56 -08:00
Jonathan Bobel
99b2fdc28a Few more updates to the <head> 2024-03-08 10:56:17 -05:00
Jonathan Bobel
5c39814daa Small style updates 2024-03-08 10:34:09 -05:00
Jonathan Bobel
f379f5de15 Updated favicon package and header styling 2024-03-08 10:11:51 -05:00
Jonathan Bobel
6a2f54367c Updated logo and og:image 2024-03-07 16:42:57 -05:00
Carlo Costino
7e2977f519 Merge pull request #1279 from GSA/dashboard_bug
dashboard bug
2024-03-07 13:52:33 -05:00
Kenneth Kehl
2be3db10d9 fix the right way 2024-03-07 10:25:11 -08:00
Kenneth Kehl
b3966ae800 revert previous commit 2024-03-07 10:17:37 -08:00
Kenneth Kehl
f42cf3bd22 rebreak the tests to reflect reality 2024-03-07 09:59:58 -08:00
Kenneth Kehl
de38f38892 fix test 2024-03-07 09:45:21 -08:00
Kenneth Kehl
111c6fd93a more fixing 2024-03-07 09:42:06 -08:00
Kenneth Kehl
c587bbee71 dashboard bug 2024-03-07 09:29:51 -08:00
Carlo Costino
0af4545436 Merge pull request #1275 from GSA/stvnrlly/add-logo-to-readme
Update README.md with logo
2024-03-07 08:21:00 -05:00
Beverly Nguyen
87b47d94df moved usa-identifier to footer tag 2024-03-06 13:04:41 -08:00
Kenneth Kehl
68163aa6d7 Use USWDS error formatting for file too big error (notify-admin-1237) 2024-03-06 11:49:19 -08:00
Beverly Nguyen
0bf289e23d removed macro and added footer.html 2024-03-06 11:49:04 -08:00
Steven Reilly
5b8377faae Update README.md 2024-03-06 14:15:37 -05:00
Carlo Costino
9a62c9df27 Merge pull request #1185 from GSA/1050-responsive-header
1050 responsive header
2024-03-05 12:56:52 -05:00
Carlo Costino
ffd911b764 Capitalize tooltip to match text 2024-03-05 12:08:59 -05:00
Jonathan Bobel
844f37bd6e Capitalized the N in Notify 2024-03-05 10:13:37 -05:00
Jonathan Bobel
026ed52ce5 When resizing the viewport for the header, I noticed other responsive issues and addressed them here 2024-03-05 09:51:25 -05:00
Carlo Costino
4635b21c01 Merge pull request #1248 from GSA/1219-delete-terms-of-use
1219 - Deleting references to the "Terms" page
2024-03-04 16:13:03 -05:00
Jonathan Bobel
0d15734110 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1050-responsive-header 2024-03-04 15:23:13 -05:00
Beverly Nguyen
d0b37cabd6 Merge remote-tracking branch 'origin/main' into 1210-create-confirmation-status-page-the-last-page-in-the-preview-send-flow 2024-03-04 11:45:06 -08:00
Carlo Costino
8091a4afd6 Merge pull request #1263 from GSA/1221-update-delivery-status-page-content
1221 - Delivery status page updates
2024-03-04 14:23:00 -05:00
Beverly Nguyen
cea10446f7 added notes and org_template 2024-03-04 11:03:22 -08:00
Carlo Costino
6e4018fc3d Merge pull request #1261 from GSA/notify-admin-1171
fix date format in batch review (notify-admin-1171)
2024-03-04 11:57:22 -05:00
Jonathan Bobel
81d89f464a small responsive styling change 2024-03-04 09:51:13 -05:00
Beverly Nguyen
996db0d60b relative path update 2024-03-01 10:38:07 -08:00
Jonathan Bobel
507973f9ae Edited the test, updated content 2024-03-01 09:34:25 -05:00
Beverly Nguyen
ebd04e44c2 revert main_Template 2024-02-29 16:38:41 -08:00
Beverly Nguyen
98297515d8 updated base.html template to also include admin-template 2024-02-29 16:36:11 -08:00
Jonathan Bobel
7d8d988f62 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1216-login-gov-pre-sign-in-page 2024-02-29 14:37:05 -05:00
Beverly Nguyen
dd37e277a5 updated relative path 2024-02-29 10:56:50 -08:00
Beverly Nguyen
51085cfc40 base.hmtl created 2024-02-29 10:49:30 -08:00
Jonathan Bobel
bdf22a1bc9 1221 - Delivery status page updates 2024-02-29 12:24:31 -05:00
Kenneth Kehl
8661a22353 fix date format in batch review (notify-admin-1171) 2024-02-29 08:24:53 -08:00
Jonathan Bobel
067b637f75 Changed the title of the pricing page to Message parts 2024-02-28 16:15:33 -05:00
Jonathan Bobel
65f365ab6d Guidance content update 2024-02-28 16:11:18 -05:00
Jonathan Bobel
f49f27bcdf Content updates to pricing page 2024-02-28 16:07:49 -05:00
Jonathan Bobel
602f2fccfd 1219 - Deleting references to the "Terms" page
I kept the actual HTML in case we want/need to add it back in the future. Can reference this branch to do so.
2024-02-27 16:38:58 -05:00
Jonathan Bobel
3775148a88 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1050-responsive-header 2024-02-27 12:49:26 -05:00
Carlo Costino
c514214fb0 Merge pull request #1226 from GSA/1225-change-padding-on-recent-batch-tables
Quick fix: added padding to td on recent table table
2024-02-27 12:49:23 -05:00
Jonathan Bobel
116953b33f Adjusting conditional logic to hide responsive menu button if navigation isn't present 2024-02-27 12:42:47 -05:00
Jonathan Bobel
0ba6f6f708 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1050-responsive-header
# Conflicts:
#	app/templates/views/security.html
2024-02-27 11:55:44 -05:00
Jonathan Bobel
a7db80ab04 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1216-login-gov-pre-sign-in-page 2024-02-27 11:53:57 -05:00
Jonathan Bobel
d5f40dffe1 Commit before merge 2024-02-27 11:53:51 -05:00
Carlo Costino
d3e4e2fd14 Merge pull request #1180 from GSA/449-one-pager-content-updates
449 one pager content updates
2024-02-27 11:24:11 -05:00
Carlo Costino
064c4d662e Merge pull request #1244 from GSA/Filter-out-empty-notifications
Filtered out empty notifications (related to recent batch table)
2024-02-27 11:08:39 -05:00
Carlo Costino
e9f9633287 Fix typo 2024-02-27 11:08:11 -05:00
Jonathan Bobel
2c6e02137b Updates per Meghan 2024-02-27 11:08:10 -05:00
Carlo Costino
271086a04d Merge pull request #1177 from GSA/bug-very-small-pricing-content-update
Bug - very small content update on pricing page
2024-02-27 10:48:17 -05:00
Carlo Costino
48bf6800f0 Merge pull request #1238 from GSA/e2e-tests-docs
Add E2E documentation and clean E2E tests
2024-02-27 10:42:50 -05:00
Jonathan Bobel
3c525b18a5 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1216-login-gov-pre-sign-in-page 2024-02-27 10:26:49 -05:00
Carlo Costino
598643b599 Merge pull request #1223 from GSA/logingovlink
enable login.gov link on demo and adjust test
2024-02-26 18:14:21 -05:00
Carlo Costino
6ec0de4b63 One final note about why the test is brittle
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-26 18:07:26 -05:00
Carlo Costino
f8b8dd5fb3 Fix broken test and include note about why
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-26 17:59:18 -05:00
Carlo Costino
92fc35b6f6 Only enable Login.gov link for demo right now
We are holding off on production until we have a chance to share more information with pilot partners.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-26 17:47:42 -05:00
Carlo Costino
4e32ef37b6 Adjust connectivity to Login.gov
- Adds Login.gov to remaining egress proxies (both prototype and production URLs)
- Swaps links to Login.gov to production environment

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-26 17:47:42 -05:00
Kenneth Kehl
470574e197 enable login.gov link on demo and production and adjust test 2024-02-26 17:47:42 -05:00
Beverly Nguyen
58e252f092 updated Delivery Status title 2024-02-26 12:25:53 -08:00
Kenneth Kehl
f332587b37 handle case where we are trying to build on github and haven't deployed yet 2024-02-26 11:48:06 -08:00
Kenneth Kehl
f245c25e59 merge from main 2024-02-26 11:10:37 -08:00
Kenneth Kehl
141c24e371 add latest version commit hash to footer (notify-admin-204) 2024-02-26 11:07:16 -08:00
Jonathan Bobel
6d05c1ab75 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1216-login-gov-pre-sign-in-page 2024-02-26 11:10:58 -05:00
Jonathan Bobel
fff440a6ff 1216 - sign-in page redesign with login.gov 2024-02-26 11:10:50 -05:00
Beverly Nguyen
66909e9624 added conditional 2024-02-23 17:50:25 -08:00
Beverly Nguyen
039b7cdece update test 2024-02-23 15:14:54 -08:00
Beverly Nguyen
d08968a348 update test 2024-02-23 15:02:18 -08:00
Beverly Nguyen
fd340ed105 update test 2024-02-23 14:59:25 -08:00
Beverly Nguyen
0981990086 update testing 2024-02-23 14:50:26 -08:00
Carlo Costino
564fc73521 Fixed up documentation to match current state; blackened formatting
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 17:38:47 -05:00
Carlo Costino
5c6a23c873 Undo changes to the landing page test
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 17:10:41 -05:00
Carlo Costino
c891bc1b3f Another attempt at fixing the landing page test
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 17:02:18 -05:00
Carlo Costino
34d20c4d65 Trying to get landing page test working again
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 16:53:39 -05:00
Beverly Nguyen
fff70d4edc fixed spacing 2024-02-23 13:37:48 -08:00
Beverly Nguyen
2ee744e56d fixed spacing 2024-02-23 13:31:49 -08:00
Beverly Nguyen
7fc5b88ea3 updated testing 2024-02-23 13:26:46 -08:00
Carlo Costino
e71351d949 Add E2E documentation and clean E2E tests
This changeset adds additional documentation for how to write new E2E tests and cleans up the two existing tests slightly to make better use of the fixtures that are defined.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 16:02:16 -05:00
Carlo Costino
15c1863ab0 Merge pull request #772 from GSA/re-enable-e2e-actions
Re-enable E2E GitHub action and get end-to-end tests working
2024-02-23 15:16:08 -05:00
Carlo Costino
fadb8094f6 Merge pull request #1064 from GSA/dependabot/pip/notifications-python-client-9.0.0
Bump notifications-python-client from 8.2.0 to 9.0.0
2024-02-23 14:43:28 -05:00
Beverly Nguyen
8ce0091cc8 Merge remote-tracking branch 'origin/main' into 1210-create-confirmation-status-page-the-last-page-in-the-preview-send-flow 2024-02-23 10:09:18 -08:00
Beverly Nguyen
df47a6ea8a Merge remote-tracking branch 'origin/main' into 1169-display-confirmation-summary-on-the-preview-page 2024-02-23 10:05:53 -08:00
dependabot[bot]
25646c2e2f Bump notifications-python-client from 8.2.0 to 9.0.0
Bumps [notifications-python-client](https://github.com/alphagov/notifications-python-client) from 8.2.0 to 9.0.0.
- [Changelog](https://github.com/alphagov/notifications-python-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/alphagov/notifications-python-client/compare/8.2.0...9.0.0)

---
updated-dependencies:
- dependency-name: notifications-python-client
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 17:18:04 +00:00
Carlo Costino
ffba252773 Merge pull request #1065 from GSA/dependabot/pip/flake8-7.0.0
Bump flake8 from 6.1.0 to 7.0.0
2024-02-23 12:11:11 -05:00
dependabot[bot]
c71a7edcfe Bump flake8 from 6.1.0 to 7.0.0
Bumps [flake8](https://github.com/pycqa/flake8) from 6.1.0 to 7.0.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.1.0...7.0.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 17:01:47 +00:00
Carlo Costino
8e176d5cf5 Merge pull request #1131 from GSA/dependabot/pip/vulture-2.11
Bump vulture from 2.10 to 2.11
2024-02-23 11:55:24 -05:00
dependabot[bot]
673df7da3d Bump vulture from 2.10 to 2.11
Bumps [vulture](https://github.com/jendrikseipp/vulture) from 2.10 to 2.11.
- [Release notes](https://github.com/jendrikseipp/vulture/releases)
- [Changelog](https://github.com/jendrikseipp/vulture/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jendrikseipp/vulture/compare/v2.10...v2.11)

---
updated-dependencies:
- dependency-name: vulture
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 16:50:02 +00:00
Carlo Costino
5c0cd73d91 Merge pull request #1205 from GSA/dependabot/pip/black-24.2.0
Bump black from 23.12.1 to 24.2.0
2024-02-23 11:43:59 -05:00
Carlo Costino
4741b381c2 Adjusting authenticated page fixture
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:39:14 -05:00
dependabot[bot]
d0c4b505b9 Bump black from 23.12.1 to 24.2.0
Bumps [black](https://github.com/psf/black) from 23.12.1 to 24.2.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.12.1...24.2.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 16:35:56 +00:00
Carlo Costino
0a8794966e Merge pull request #1229 from GSA/dependabot/pip/coverage-7.4.2
Bump coverage from 7.4.0 to 7.4.2
2024-02-23 11:33:53 -05:00
Carlo Costino
4180dca164 Last bits of cleanup with pytest configuration for E2E tests
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:24:03 -05:00
dependabot[bot]
b50fe24c52 Bump coverage from 7.4.0 to 7.4.2
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.0 to 7.4.2.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.4.0...7.4.2)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 16:14:06 +00:00
Carlo Costino
9c392bca78 Switch E2E test command to use Makefile
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:38 -05:00
Carlo Costino
7259d617ee Actually disable webkit in CI/CD E2E tests
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:38 -05:00
Carlo Costino
fd5cd36959 Remove webkit testing for now
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:38 -05:00
Carlo Costino
3a6eeb2292 Swapping API back to development environment
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:38 -05:00
Carlo Costino
bd41dfc1c2 Attempting to get E2E work with local API
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
534daa2d82 Attempting to match local E2E config with CI/CD
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
c790d8b844 Added some additional environment variables to E2E command
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
719ecfe8f6 Modified E2E test job environment
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
1b6446e213 Added a new E2ETest config and adjusted a couple of things
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
29c20a0ee9 Trying to see if New Relic needs to be in place
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:37 -05:00
Carlo Costino
5aacdcbc35 Slight adjustments to make sure no typos are present
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
c2e7b4897d Adjusting a couple of other environment variables
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
136403a263 Adding a couple more missing env vars for the admin server
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
aec20b5e73 Add API access to Admin server
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
95bdd335eb Changing back to staging API; trying to get E2E auth working
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
87ca03f6d8 Switch back to using the API locally in the CI/CD job
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:36 -05:00
Carlo Costino
9987946f92 Trying one more environment variable for auth
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
e8e23e3ac0 A little more cleanup
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
997aa8e72f Added missing environment variables for the server process
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
c652c17617 Clean up and fix the E2E tests so that they run
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
46be3cd7b3 Add a missing slash in the test URI
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
2201c16a2b Now try to run the E2E tests!
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:35 -05:00
Carlo Costino
84559e0574 Switch Admin site environment to development
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
b9a7e48e78 Attempting to work against staging API
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
558296684c Attempting to run actual E2E tests again to see real errors
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
3ba9a85845 Adjusting API environment to development
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
57cd123f4e Adding Redis for running the API
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
6b98cf7c35 Reverting previous change of the DB name
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:34 -05:00
Carlo Costino
91527f32f2 Changing DB name to match Makefile bootstrap command
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
9c32fa2d4e Adding in missing DATABASE_URL environment variable
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
b60dc00f0e A bit of cleanup and debugging comment to resume after holidays!
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
92b33834e8 Trying to discern if there is a difference in local URLs
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
5e7319cbac Testing to see if we can connect to the local server.
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
d544d7c8f8 Now trying to run the Admin server with PR code...
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:33 -05:00
Carlo Costino
b8b330f55b Attempting to get API up and running
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
bb242dc7d7 Adjusted API clone and working directory
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
f8c48f7711 Now trying to install API dependencies...
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
3003f82223 Attempting to get the API cloned at least
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
5a39165644 Just trying to get the new job to run
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
891cec5300 Uncommenting E2E test job
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:32 -05:00
Carlo Costino
89b6e13afb Just trying to get the workflow to run
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:31 -05:00
Carlo Costino
d25f0869e0 First attempt at getting the API to run for E2E tests
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:31 -05:00
Carlo Costino
4b39d5ffe9 Re-enable E2E GitHub action jobs
This changeset re-enables the GitHub action jobs we had to disable to make it possible to deploy recent changes.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-23 11:09:31 -05:00
Beverly Nguyen
1e60da1a37 add job status 2024-02-22 11:59:12 -08:00
Carlo Costino
164a414d22 Merge pull request #1230 from GSA/notify-admin-1228
change batch file report to look like full csv report
2024-02-22 14:47:58 -05:00
Carlo Costino
759a90ca47 Merge pull request #1233 from GSA/utils-0-2-9
Update utils to 0.2.9
2024-02-22 10:51:21 -05:00
Carlo Costino
14b68c044f Update utils to 0.2.9
quote>
quote> This changeset updates notifications-utils to 0.2.9 to account for a recent cryptography update.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-21 15:51:05 -05:00
Kenneth Kehl
393dddea61 update notifications-utils again 2024-02-21 12:49:26 -08:00
Kenneth Kehl
c20ec80753 update notifications-utils? 2024-02-21 11:46:26 -08:00
Kenneth Kehl
96d5e72514 change Recipient to Phone Number 2024-02-21 10:30:24 -08:00
Kenneth Kehl
3363cc6979 change test phone number 2024-02-21 09:09:45 -08:00
Kenneth Kehl
4742cc77b5 change batch file report to look like full csv report 2024-02-21 07:45:21 -08:00
Beverly Nguyen
60bcd9ddbd added padding to td 2024-02-20 11:56:26 -08:00
Beverly Nguyen
e3ff679b5e added padding to td 2024-02-20 11:32:05 -08:00
Carlo Costino
163596267a Merge pull request #1204 from GSA/fix_login_gov_link
clean up login.gov link
2024-02-20 10:46:58 -05:00
Carlo Costino
50511e1cea Merge pull request #1203 from GSA/1189-bug-norfolk-batches-table-repeats-one-batch
Bugfix: Recent Batches table repeats #1189
2024-02-20 10:34:12 -05:00
Beverly Nguyen
2e7aeb1dbf fixed test 2024-02-16 18:05:13 -08:00
Beverly Nguyen
02d1c2b26e fixed test 2024-02-16 18:01:36 -08:00
Beverly Nguyen
c383884017 fixed test 2024-02-16 17:19:03 -08:00
Beverly Nguyen
442ff5dab2 merge main 2024-02-16 11:54:59 -08:00
Beverly Nguyen
44ec565d57 Merge remote-tracking branch 'origin/main' into 1169-display-confirmation-summary-on-the-preview-page 2024-02-16 11:50:01 -08:00
Beverly Nguyen
eccf8cb3e7 added new change from ux meeting as requested 2024-02-16 11:44:25 -08:00
Carlo Costino
7471cefd2b Merge pull request #1193 from GSA/notify-api-771b
Notify api 771 fix columns in reports
2024-02-16 09:59:32 -05:00
Beverly Nguyen
d7606b2986 added PR requested changes 2024-02-15 10:40:15 -08:00
Carlo Costino
048872fb12 Merge pull request #1181 from GSA/service-bundle-stats
Bundle stats with service object
2024-02-14 17:55:40 -05:00
Carlo Costino
ddf017707f Merge pull request #1197 from GSA/notify-admin-1194
make ChooseTimeForm time zone aware
2024-02-14 17:48:52 -05:00
Carlo Costino
ebccd64242 Merge pull request #1196 from GSA/1190-bug-table-wrapping
1190 - bug - URL not wrapping in table
2024-02-14 17:47:44 -05:00
Carlo Costino
72587524a7 Merge pull request #1174 from GSA/1166-team-member-card-bug
1166 team member card bug
2024-02-14 17:41:10 -05:00
Kenneth Kehl
53549495ea remove Type and change Job to Batch File 2024-02-14 10:39:52 -08:00
Kenneth Kehl
6c66fcb125 merge from main 2024-02-14 10:23:57 -08:00
Carlo Costino
c4b8ba6c66 Merge pull request #1199 from GSA/1154-time-zone-glitch
1154 - removing default selection when selecting a time zone
2024-02-14 10:22:40 -05:00
Beverly Nguyen
4eb886d8c0 update test 2024-02-13 18:18:13 -08:00
Beverly Nguyen
c2d7828138 created an alert for confirmation during send flow 2024-02-13 17:48:06 -08:00
Beverly Nguyen
843e4bb2fa fixed testing and removed recipient 2024-02-13 16:18:50 -08:00
Beverly Nguyen
01eac988f1 fixed testing 2024-02-13 14:02:05 -08:00
Beverly Nguyen
49d270521a revision requestsed changes 2024-02-13 13:29:38 -08:00
Beverly Nguyen
49c5f57d81 limit 5 in table 2024-02-12 16:34:54 -08:00
Beverly Nguyen
dd902468f2 updated css table widths 2024-02-12 16:33:41 -08:00
Beverly Nguyen
ef5ed8ecab updated pytest 2024-02-12 15:29:26 -08:00
Kenneth Kehl
b034f1eb79 clean up login.gov link 2024-02-12 10:53:15 -08:00
Steven Reilly
c74575a0b8 Merge pull request #1202 from GSA/add-pr-template
Admin:  Add a pull request template
2024-02-12 10:04:16 -05:00
Beverly Nguyen
7b8a187db0 update sort imports 2024-02-09 17:19:15 -08:00
Beverly Nguyen
b7f21a6efd update sort imports 2024-02-09 17:15:44 -08:00
Beverly Nguyen
72aa14fd3b fixed duplicates to notification by adding aggregate 2024-02-09 17:09:48 -08:00
Carlo Costino
48f1c7c864 Admin: Add a pull request template
This changeset adds a template to the repository for our pull requests.  The intention is two-fold:

- To make it easier to know what information and details to include in our pull requests
- To improve the quality and usefulness of our pull requests

This is a start and we will be adjusting this over time as we learn more and refine our process.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-09 17:43:01 -05:00
Kenneth Kehl
2aa9f2c532 remove carrier column 2024-02-09 07:27:28 -08:00
Beverly Nguyen
b019dc3fe9 updated pytest 2024-02-08 18:43:17 -08:00
Jonathan Bobel
7832797628 Just removing the default selection 2024-02-08 15:10:07 -05:00
Jonathan Bobel
fb469545b4 1154 - pushing up this change so Ken can take a look 2024-02-08 12:09:01 -05:00
Kenneth Kehl
330fad469e make ChooseTimeForm time zone aware 2024-02-07 12:14:00 -08:00
Jonathan Bobel
456091996e 1190 - bug - URL not wrapping in table 2024-02-07 13:57:21 -05:00
Jonathan Bobel
3adce5842a Merge branch 'main' of https://github.com/GSA/notifications-admin into 1166-team-member-card-bug 2024-02-07 09:35:19 -05:00
Jonathan Bobel
72ab167265 Merge branch 'main' of https://github.com/GSA/notifications-admin into bug-very-small-pricing-content-update 2024-02-07 09:34:40 -05:00
Jonathan Bobel
bec550aca4 Merge branch 'main' of https://github.com/GSA/notifications-admin into 1050-responsive-header 2024-02-07 09:20:01 -05:00
Beverly Nguyen
fbf902e168 fixed style checks 2024-02-06 17:14:46 -08:00
Beverly Nguyen
15105bf506 fixed style checks 2024-02-06 17:06:18 -08:00
Beverly Nguyen
8eb329b444 removing comments 2024-02-06 16:42:11 -08:00
Beverly Nguyen
10d3a87bcb Merge remote-tracking branch 'origin/main' into 1169-display-confirmation-summary-on-the-preview-page 2024-02-06 16:09:15 -08:00
Beverly Nguyen
d6f012ee9e editing and creating new preview functions and backlinks 2024-02-06 16:08:14 -08:00
Kenneth Kehl
2962fc36c4 merge from main 2024-02-06 14:57:40 -08:00
Carlo Costino
ad34ca0a11 Merge pull request #1192 from GSA/govuk_frontend_jinja
inline code for govuk_frontend_jinja
2024-02-06 16:48:23 -05:00
Carlo Costino
df54b066f9 Update notifications-utils to 0.2.8
This updates utils to be 0.2.8 to address the cryptography Dependabot security alert.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-02-06 16:41:07 -05:00
Kenneth Kehl
338a6426c3 inline code for govuk_frontend_jinja 2024-02-06 13:17:09 -08:00
Carlo Costino
f37903ff6d Merge pull request #1183 from GSA/notify-admin-1159
Notify admin 1159 -- update to use sent_at instead of updated_at
2024-02-05 17:20:53 -05:00
Kenneth Kehl
80135b2ff6 notify-api-771 fix columns in reports 2024-02-05 12:27:40 -08:00
Jonathan Bobel
74d8ed8340 1050 - Fixing repsonsive issues in the header - and beyond 2024-02-05 13:32:53 -05:00
Beverly Nguyen
c073d2efac revising message preview 2024-02-02 16:14:50 -08:00
Beverly Nguyen
3ac65b122c inital preview page 2024-02-02 14:52:48 -08:00
Kenneth Kehl
802ebfa243 use sent_at instead of updated_at 2024-02-02 08:31:05 -08:00
Andrew Shumway
10f732b390 Bundle stats with service object 2024-02-01 11:37:31 -07:00
Jonathan Bobel
d82b56c644 Updates per Meghan 2024-02-01 12:09:43 -05:00
Jonathan Bobel
93a36cce79 Merge branch 'main' of https://github.com/GSA/notifications-admin into 449-one-pager-content-updates 2024-02-01 11:06:49 -05:00
Tim Lowden
e18054d2d8 Merge pull request #1160 from GSA/449-one-pager-content-updates
449 one pager content updates
2024-02-01 09:15:57 -05:00
Kenneth Kehl
21c11adb5e fix sent time 2024-01-31 10:27:56 -08:00
Jonathan Bobel
3e52909e88 Merge branch 'main' of https://github.com/GSA/notifications-admin into 449-one-pager-content-updates 2024-01-31 11:12:55 -05:00
Jonathan Bobel
4e63a601e9 Bug - very small content update on pricing page 2024-01-31 11:10:46 -05:00
Carlo Costino
266b530e3a Merge pull request #1175 from GSA/add-login-gov-env-vars
Add Login.gov configuration to prod and demo environments
2024-01-30 17:26:34 -05:00
Carlo Costino
6af738e0de Add Login.gov configuration to prod and demo environments
This changeset adds the required Login.gov environment variables to the production and demo environments so that deployments function correctly.

NOTE:  This will not fully enable Login.gov integration just yet; more configuration needs to be adjusted and the Login.gov app needs to be promoted to production itself.
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-30 17:21:29 -05:00
Jonathan Bobel
f97bfa863f Updated button styles 2024-01-30 15:28:15 -05:00
Jonathan Bobel
0021d64253 1166 - Adjusting the card width and wrapping styles 2024-01-30 15:23:21 -05:00
Carlo Costino
27385bc45a Merge pull request #1170 from GSA/fix-infrastructure-checks
Fix Terraform commands and actions
2024-01-30 15:04:35 -05:00
Carlo Costino
f097b9ca07 Merge pull request #1167 from GSA/notify-admin-1148
notify-admin-1148 make sure one-off files get written to db
2024-01-30 11:38:58 -05:00
Carlo Costino
50e3560c6f Remove the profile attribute entirely
This was what was apparently breaking our Terraform actions.  I traced this to an undocumented breaking change with the AWS provider; more details can be seen here: https://discuss.hashicorp.com/t/error-error-configuring-terraform-aws-provider-failed-to-get-shared-config-profile-default/39417/2

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-30 11:06:13 -05:00
Jonathan Bobel
761c7bd0fd Updated security content page 2024-01-30 09:49:04 -05:00
Carlo Costino
4da5c14751 Updated 18F/terraform-cloudgov to v0.7.1
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-30 09:40:14 -05:00
Carlo Costino
0f167a91cc Update Cloud Foundry Terraform module
This changeset updates the Cloud Foundry Terraform to its latest release.  Our file were previously referencing a very old version, which was contributing to infrastructure check and deployment failures.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-30 09:26:04 -05:00
Kenneth Kehl
7c5674c4e1 notify-admin-1137 make sure one-off files get written to db 2024-01-29 13:17:50 -08:00
Jonathan Bobel
6d3c92de28 Merge branch 'main' of https://github.com/GSA/notifications-admin into 449-one-pager-content-updates 2024-01-29 10:32:17 -05:00
Jonathan Bobel
e40a493f9b Updated Roadmap content 2024-01-29 10:28:59 -05:00
Carlo Costino
4e488fa079 Merge pull request #1162 from GSA/1161-bug-fix-ui-time-sent-column-to-match-time-the-message-was-created_at
BUG: Fix UI Time Sent column to match time the message was created_at
2024-01-26 16:48:40 -05:00
Beverly Nguyen
5d480b3f53 updated time 2024-01-26 13:37:49 -08:00
Jonathan Bobel
070955175d Merge branch 'main' of https://github.com/GSA/notifications-admin into 449-one-pager-content-updates 2024-01-26 15:22:30 -05:00
Carlo Costino
a5eb311f83 Merge pull request #1129 from GSA/1114-reviseexpand-on-recent-batch-table-on-the-dashboard-page
Revise/expand on "Recent Batch" table on the dashboard page.
2024-01-26 15:03:08 -05:00
Beverly Nguyen
6b4a5d009c removed comment 2024-01-26 11:51:52 -08:00
Beverly Nguyen
1f12dd3908 show only the first 5 rows 2024-01-26 11:47:46 -08:00
Jonathan Bobel
0e64ff1c20 Contact us page 2024-01-26 14:34:25 -05:00
Beverly Nguyen
f7924320df adjusted styling 2024-01-26 11:32:42 -08:00
Beverly Nguyen
1b4754386c update testing for signout and accept invite 2024-01-26 11:29:03 -08:00
Jonathan Bobel
a27519ff68 Removed white space 2024-01-26 14:20:47 -05:00
Jonathan Bobel
b72430af63 Guidance page 2024-01-26 14:20:23 -05:00
Beverly Nguyen
35b38f838c fixed testing for dashboard.py 2024-01-26 11:16:45 -08:00
Beverly Nguyen
45ffa70c3c fixing mocker patch for jobs 2024-01-26 09:43:41 -08:00
Jonathan Bobel
bd33fe4750 Merge branch 'main' of https://github.com/GSA/notifications-admin into 449-one-pager-content-updates 2024-01-26 10:20:37 -05:00
Jonathan Bobel
768f1986e8 449 - Content updates
- Get started
2024-01-26 10:10:49 -05:00
Carlo Costino
e48cb94ccb Merge pull request #1143 from GSA/963-message-parts-content-updates
963 message parts content updates
2024-01-26 09:40:17 -05:00
Carlo Costino
0fc14131b1 Merge pull request #1147 from GSA/dependabot/pip/newrelic-9.6.0
Bump newrelic from 9.5.0 to 9.6.0
2024-01-26 09:28:38 -05:00
Beverly Nguyen
6e05fd5147 removed comments 2024-01-25 15:39:32 -08:00
dependabot[bot]
c79c824b24 Bump newrelic from 9.5.0 to 9.6.0
Bumps [newrelic](https://github.com/newrelic/newrelic-python-agent) from 9.5.0 to 9.6.0.
- [Release notes](https://github.com/newrelic/newrelic-python-agent/releases)
- [Commits](https://github.com/newrelic/newrelic-python-agent/compare/v9.5.0...v9.6.0)

---
updated-dependencies:
- dependency-name: newrelic
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-25 23:32:58 +00:00
Beverly Nguyen
524a1e4687 updated download links and table html 2024-01-25 15:32:44 -08:00
Carlo Costino
9513069b42 Merge pull request #1146 from GSA/tdlowden-patch-1
Create manual_qa_template.yml
2024-01-25 16:16:49 -05:00
Tim Lowden
af8309a2ce Update manual_qa_template.yml 2024-01-25 16:07:58 -05:00
Tim Lowden
37086cb03b Update manual_qa_template.yml 2024-01-25 15:57:29 -05:00
Tim Lowden
3ac9d44b2a Update manual_qa_template.yml 2024-01-25 15:56:28 -05:00
Tim Lowden
d5210427f0 Create manual_qa_template.yml
Just starting this
2024-01-25 15:52:59 -05:00
Jonathan Bobel
da1e2a2700 Merge branch 'main' of https://github.com/GSA/notifications-admin into 963-message-parts-content-updates 2024-01-25 14:55:22 -05:00
Jonathan Bobel
d9875ef287 Content updates for Pricing, Trial Mode, and various areas of changing "message parts" 2024-01-25 14:55:17 -05:00
Steven Reilly
cdd262365f Merge pull request #1141 from GSA/update-utils-0-2-7
Update notifications-utils to 0.2.7
2024-01-24 16:05:48 -05:00
Carlo Costino
195c68037b Merge pull request #1140 from GSA/notify-admin-1090
change download reports to 12 hour time (notify-admin-1090)
2024-01-24 15:53:22 -05:00
Carlo Costino
d5daab67cf Fixes tests to match recent notifications-utils updates
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-24 15:35:09 -05:00
Jonathan Bobel
782ec1c5eb 963 - content updates 2024-01-24 15:25:19 -05:00
Kenneth Kehl
fd8981d5cd add timezone to file name 2024-01-24 11:59:31 -08:00
Carlo Costino
1709d3279b Update notifications-utils to 0.2.7
This changeset updates the notifications-utils library to 0.2.7.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-24 14:55:55 -05:00
Kenneth Kehl
2126ba8038 fix name of download file 2024-01-24 11:54:25 -08:00
Beverly Nguyen
c9ed1ab59d change time column 2024-01-24 11:15:35 -08:00
Kenneth Kehl
a38518777c change download reports to 12 hour time 2024-01-24 11:03:19 -08:00
Carlo Costino
3379259e14 Merge pull request #1136 from GSA/dependabot/pip/python-dotenv-1.0.1
Bump python-dotenv from 1.0.0 to 1.0.1
2024-01-24 13:55:52 -05:00
dependabot[bot]
ede82d76d6 Bump python-dotenv from 1.0.0 to 1.0.1
Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: python-dotenv
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-24 18:34:27 +00:00
Carlo Costino
5970dd8055 Merge pull request #1135 from GSA/dependabot/pip/bandit-1.7.7
Bump bandit from 1.7.6 to 1.7.7
2024-01-24 13:31:53 -05:00
Beverly Nguyen
65bccb3f95 changed time column 2024-01-23 16:18:43 -08:00
dependabot[bot]
75a4e1ae6d Bump bandit from 1.7.6 to 1.7.7
Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.6 to 1.7.7.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.6...1.7.7)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 23:36:48 +00:00
Beverly Nguyen
8baf9682a1 update table css and format 2024-01-23 15:24:57 -08:00
Steven Reilly
6b00cf1270 Merge pull request #1133 from GSA/set-no-proxy-exclusion
Add no_proxy environment variable
2024-01-22 16:27:45 -05:00
Carlo Costino
490174ab71 Add no_proxy environment variable
This changeset adds the no_proxy environment variable to be set at the time our app runs to exclude the internal apps running within our platform that are handled by Cloud Foundry network policies instead.  Without this in place, the egress proxy will not allow our deployed apps to talk with one another.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-22 15:36:00 -05:00
Carlo Costino
f15643c04d Merge pull request #1130 from GSA/adjust-egress-proxy-config
Add missing egress proxy configuration
2024-01-19 17:19:09 -05:00
Carlo Costino
d253b601a2 Add missing egress proxy configuration
This changeset adds some egress proxy configuration that is currently missing from the application initialization.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-01-19 17:14:11 -05:00
Beverly Nguyen
9b0dc3dc3c updated table titles and fields 2024-01-19 11:44:25 -08:00
Carlo Costino
443c7d9992 Merge pull request #1106 from GSA/tdlowden-patch-1
Update sprint-goals.md
2024-01-18 16:27:44 -05:00
Tim Lowden
33433a3822 Update sprint-goals.md 2024-01-18 12:45:03 -05:00
Tim Lowden
c7a393e620 Update sprint-goals.md 2024-01-18 12:43:55 -05:00
Tim Lowden
ba3a229d60 Update sprint-goals.md 2024-01-18 12:42:33 -05:00
Jonathan Bobel
17b1352f01 Merge pull request #1121 from GSA/tdlowden-patch-3
Update bug_template.yml
2024-01-18 11:38:32 -05:00
Tim Lowden
a1440ae36f Update bug_template.yml 2024-01-18 11:33:20 -05:00
Tim Lowden
d49fb8867e Update bug_template.yml 2024-01-18 11:30:43 -05:00
Carlo Costino
98b11dc3c4 Merge pull request #1103 from GSA/818-allow-single-messages-to-be-scheduled
Allow single messages to be scheduled #818
2024-01-18 11:07:00 -05:00
Carlo Costino
6fe29a2bdd Merge pull request #1101 from GSA/1089-change-team-member-card-width
1089 change team member card width
2024-01-18 10:30:00 -05:00
Tim Lowden
b463d420ef Merge pull request #1119 from GSA/fixing-the-bug-template
Replicated the User Story Template in a few ways to see if that fixes…
2024-01-18 10:28:04 -05:00
Carlo Costino
2a9f60c32e Merge pull request #1100 from GSA/1022-sentence-about-5-minutes-til-message-receipts-doesnt-appear
Sentence about 5 minutes til message receipts doesn't appear #1022
2024-01-18 10:19:14 -05:00
Tim Lowden
adda14342b Update sprint-goals.md 2024-01-17 10:07:55 -05:00
Beverly Nguyen
d3c3183573 added choose time form 2024-01-16 15:37:56 -08:00
Beverly Nguyen
25305d0706 update testing 2024-01-16 12:01:39 -08:00
Beverly Nguyen
0e110201d6 update testing 2024-01-16 11:28:58 -08:00
Beverly Nguyen
11a85d688a added notifications status 2024-01-15 14:17:18 -08:00
Jonathan Bobel
82863b02ce Merge branch 'main' of https://github.com/GSA/notifications-admin into 1089-change-team-member-card-width 2024-01-11 16:00:04 -05:00
Jonathan Bobel
27c74ca773 1089- styling update to Team Member cards 2024-01-11 15:56:17 -05:00
176 changed files with 4698 additions and 2963 deletions

View File

@@ -5,8 +5,6 @@ title: "Bug: [Brief description of the bug]"
labels:
- "Type: Bug"
assignees:
body:
- type: markdown
attributes:
@@ -29,6 +27,17 @@ body:
value: "A bug happened!"
validations:
required: true
- type: dropdown
id: environment
attributes:
label: Environment
description: In which environment did you experience the bug?
options:
- staging
- demo
- production
validations:
required: true
- type: textarea
id: page
attributes:
@@ -36,6 +45,13 @@ body:
description: please include URLs of where you saw the bug
validations:
required: true
- type: textarea
id: reproSteps
attributes:
label: "Detail the steps for someone to reproduce"
description: "Reproduction steps"
validations:
required: true
- type: dropdown
id: browsers
attributes:
@@ -52,4 +68,4 @@ body:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
required: false

View File

@@ -0,0 +1,82 @@
name: "QA Checklist"
description: "Use this template to manually QA for prod push"
title: "QA for prod push: Admin #[insert PR number], API #[insert PR number], Utils #[insert PR number]"
body:
- type: checkboxes
id: Logging_in
attributes:
label: Log In
options:
- label: notify-staging.app.cloud.gov resolves
- label: Clicking sign in takes you to login page
- label: 2FA code is sent promptly
- label: 2FA code input screen appears as expected
- label: After code is entered, you are brought to the “choose service” screen
- label: Choosing a service brings you to the dashboard for that service
- type: checkboxes
id: send_template
attributes:
label: Create a template and send
options:
- label: Clicking “Send messages” brings you to templates page
- label: When “Create a template” button is clicked, the option to create new or copy existing template appears
- label: Uploading a csv is quick and automatically directs you to the preview/send page
- label: Formatting looks clean and in place
- label: Message dashboard populates and shows “pending” until call is made to AWS for delivery receipt
- type: checkboxes
id: send__copied_template
attributes:
label: Send a message from copied template
options:
- label: When “Create a template” button is clicked, the option to create new or copy existing template appears
- label: Clicking “copy an existing template” allows you to choose from pre-existing template
- label: After editing, the new template saves and you prepare to send
- type: checkboxes
id: send__existing_template
attributes:
label: Send a message from existing template
options:
- label: Clicking on existing template brings you to preview screen with `prepare to send` button
- label: All else above persists as true (formatting, send, dashboard, etc)
- type: checkboxes
id: download_report
attributes:
label: Download the csv delivery report
options:
- label: Clicking on the csv download directly after a message send downloads a report that contains the data we expect
- label: The batch report appears on the main dashboard batch table with accurate information
- label: Clicking on the csv download link from the main dashboard downloads a report that contains the data we expect
- type: checkboxes
id: invite_member
attributes:
label: Invite a team member
options:
- label: Clicking on “Team” in settings brings you to team member screen
- label: Clicking “Invite a team member” brings you to email and permissions screen
- label: Clicking invite team member sends an invite and shows confirmation
- label: Invite email provides live link that works to register new team member
- type: checkboxes
id: delete_member
attributes:
label: Delete a team member
options:
- label: From team member screen, clicking “Change Details” on a specific profile brings you to that persons profile
- label: Clicking on “Remove this team member” prompts a confirmation
- label: Clicking the confirmation removes the team member
- type: checkboxes
id: sign_out
attributes:
label: Sign Out
options:
- label: Hitting “Sign Out” takes you back to the homepage and logs you out

View File

@@ -9,10 +9,10 @@ runs:
sudo apt-get update \
&& sudo apt-get install -y --no-install-recommends \
libcurl4-openssl-dev
- name: Set up Python 3.9
uses: actions/setup-python@v3
- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: "3.9"
python-version: "3.12"
- name: Install poetry
shell: bash
run: pip install poetry

79
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,79 @@
<!--
Please follow the instructions found in this pull request template so that we
have all of the relevant details needed for our work.
At the minimum, please be sure to fill in all sections found below and also do
the following:
- Provide an appropriate and descriptive title for the pull request
- Link the pull request to its corresponding issue (must be done after creating
the pull request itself)
- Assign yourself as the author
- Attach the appropriate labels to it
- Set it to be on the Notify.gov project board
- Select one or more reviewers from the team or mark the pull request as a draft
depending on its current state
- If the pull request is a draft, please be sure to add reviewers once it is
ready for review and mark it ready for review
For each section, please delete the instructions/sample text (that includes this
text, though it is wrapped in an HTML comment just in case) and put in your own
information. Thank you!
-->
*A note to PR reviewers: it may be helpful to review our
[code review documentation](https://github.com/GSA/notifications-api/blob/main/docs/all.md#code-reviews)
to know what to keep in mind while reviewing pull requests.*
## Description
Please enter a clear description about your proposed changes and what the
expected outcome(s) is/are from there. If there are complex implementation
details within the changes, this is a great place to explain those details using
plain language.
This should include:
- Links to issues that this PR addresses
- Screenshots or screen captures of any visible changes, especially for UI work
- Dependency changes
If there are any caveats, known issues, follow-up items, etc., make a quick note
of them here as well, though more details are probably warranted in the issue
itself in this case.
## TODO (optional)
If you're opening a draft PR, it might be helpful to list any outstanding work,
especially if you're asking folks to take a look before it's ready for full
review. In this case, create a small checklist with the outstanding items:
- [ ] TODO item 1
- [ ] TODO item 2
- [ ] TODO item ...
## Security Considerations
Please think about the security compliance aspect of your changes and what the
potential impacts might be.
**NOTE: Please be mindful of sharing sensitive information here! If you're not
sure of what to write, please ask the team first before writing anything here.**
Relevant details could include (and are not limited to) the following:
- Handling secrets/credential management (or specifically calling out that there
is nothing to handle)
- Any adjustments to the flow of data in and out the system, or even within it
- Connecting or disconnecting any external services to the application
- Handling of any sensitive information, such as PII
- Handling of information within log statements or other application monitoring
services/hooks
- The inclusion of a new external dependency or the removal of an existing one
- ... (anything else relevant from a security compliance perspective)
There are some cases where there are no security considerations to be had, e.g.,
updating our documentation with publicly available information. In those cases
it is fine to simply put something like this:
- None; this is a documentation update with publicly available information.

View File

@@ -7,12 +7,12 @@ permissions:
env:
NOTIFY_ENVIRONMENT: test
NEW_RELIC_CONFIG_FILE: newrelic.ini
NEW_RELIC_ENVIRONMENT: test
FLASK_APP: application.py
WERKZEUG_DEBUG_PIN: off
REDIS_ENABLED: 0
NODE_VERSION: 16.15.1
AWS_US_TOLL_FREE_NUMBER: "+18556438890"
ADMIN_BASE_URL: http://localhost:6012
jobs:
build:
@@ -22,7 +22,7 @@ jobs:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- uses: jwalton/gh-find-current-pr@v1
id: findPr
@@ -44,38 +44,107 @@ jobs:
run: npm test
- name: Run py tests with coverage
run: poetry run coverage run --omit=*/notifications_utils/* -m pytest --maxfail=10 --ignore=tests/end_to_end tests/
# - name: Run E2E tests
# run: poetry run pytest -v --browser chromium --browser firefox --browser webkit tests/end_to_end
# env:
# NOTIFY_E2E_AUTH_STATE_PATH: ${{ secrets.NOTIFY_E2E_AUTH_STATE_PATH }}
# NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
# NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
# NOTIFY_E2E_TEST_URI: ${{ secrets.NOTIFY_E2E_TEST_URI }}
- name: Check coverage threshold
run: poetry run coverage report --fail-under=90
# - name: Health check
# run: |
# response=$(curl -url ${{secrets.NOTIFY_E2E_TEST_URI}}_status)
# if grep -q "ok" <<< "$response"; then
# echo "Health check passed"
# else
# echo "Health check failed"
# exit 1
# fi
# env:
# NOTIFY_E2E_AUTH_STATE_PATH: ${{ secrets.NOTIFY_E2E_AUTH_STATE_PATH }}
# NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
# NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
# NOTIFY_E2E_TEST_URI: ${{ secrets.NOTIFY_E2E_TEST_URI }}
end-to-end-tests:
permissions:
checks: write
pull-requests: write
contents: write
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: test_notification_api
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
# Maps tcp port 5432 on service container to the host
- 5432:5432
redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
# Maps tcp port 6379 on service container to the host
- 6379:6379
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- uses: jwalton/gh-find-current-pr@v1
id: findPr
- name: Clone API
uses: actions/checkout@v4
with:
repository: GSA/notifications-api
path: 'notifications-api'
- name: Install API dependencies
working-directory: 'notifications-api'
run: make bootstrap
env:
DATABASE_URL: postgresql://user:password@localhost:5432/test_notification_api
SQLALCHEMY_DATABASE_TEST_URI: postgresql://user:password@localhost:5432/test_notification_api
REDIS_URL: redis://localhost:6379
NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
NOTIFY_ENVIRONMENT: development
- name: Run API server
working-directory: 'notifications-api'
run: make run-procfile &
env:
DATABASE_URL: postgresql://user:password@localhost:5432/test_notification_api
SQLALCHEMY_DATABASE_TEST_URI: postgresql://user:password@localhost:5432/test_notification_api
REDIS_URL: redis://localhost:6379
NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
NOTIFY_ENVIRONMENT: development
- name: Run Admin server
run: make run-flask &
env:
# API_HOST_NAME: https://notify-api-staging.app.cloud.gov
API_HOST_NAME: http://localhost:6011
DANGEROUS_SALT: ${{ secrets.DANGEROUS_SALT }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }}
ADMIN_CLIENT_USERNAME: notify-admin
NOTIFY_ENVIRONMENT: e2etest
NOTIFY_E2E_AUTH_STATE_PATH: ${{ secrets.NOTIFY_E2E_AUTH_STATE_PATH }}
NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
NOTIFY_E2E_TEST_URI: http://localhost:6012
- name: Run E2E tests
# Run the E2E tests against the code found in this PR.
# run: poetry run pytest -v --browser chromium --browser firefox --browser webkit tests/end_to_end
# --browser webkit doesn't work at this time.
run: make e2e-test
# Debugging for now to troubleshoot a connectivity issue to the local servers
# run: curl --request GET --url "http://localhost:6012"
env:
NOTIFY_ENVIRONMENT: e2etest
NOTIFY_E2E_AUTH_STATE_PATH: ${{ secrets.NOTIFY_E2E_AUTH_STATE_PATH }}
NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }}
NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }}
NOTIFY_E2E_TEST_URI: http://localhost:6012
validate-new-relic-config:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Validate NewRelic config
env:
NEW_RELIC_CONFIG_FILE: newrelic.ini
NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
# Need to set a NEW_RELIC_ENVIRONMENT with monitor_mode: true
NEW_RELIC_ENVIRONMENT: staging
@@ -84,7 +153,7 @@ jobs:
dependency-audits:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
@@ -97,7 +166,7 @@ jobs:
static-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Run scan
run: poetry run bandit -r app/ --confidence-level medium
@@ -105,7 +174,7 @@ jobs:
dynamic-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Run server
run: make run-flask &
@@ -124,7 +193,7 @@ jobs:
a11y-scan:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Run server
run: make run-flask &

View File

@@ -22,7 +22,7 @@ jobs:
dependency-audits:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
@@ -35,7 +35,7 @@ jobs:
static-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Run scan
run: poetry run bandit -r app/ --confidence-level medium
@@ -43,7 +43,7 @@ jobs:
dynamic-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Run server
run: make run-flask &

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
environment: demo
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2
@@ -54,7 +54,15 @@ jobs:
ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }}
NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }}
COMMIT_HASH: ${{ github.sha }}
LOGIN_PEM: ${{ secrets.LOGIN_PEM }}
LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov"
LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo"
LOGIN_DOT_GOV_ACCESS_TOKEN_URL: "https://secure.login.gov/api/openid_connect/token"
LOGIN_DOT_GOV_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&post_logout_redirect_uri=https://notify-demo.app.cloud.gov/sign-out"
LOGIN_DOT_GOV_BASE_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?"
LOGIN_DOT_GOV_SIGNOUT_REDIRECT: "https://notify-demo.app.cloud.gov/sign-out"
LOGIN_DOT_GOV_INITIAL_SIGNIN_URL: "https://secure.login.gov/openid_connect/authorize?acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&nonce=NONCE&prompt=select_account&redirect_uri=https://notify-demo.app.cloud.gov/sign-in&response_type=code&scope=openid+email&state=STATE"
with:
cf_username: ${{ secrets.CLOUDGOV_USERNAME }}
cf_password: ${{ secrets.CLOUDGOV_PASSWORD }}
@@ -68,7 +76,15 @@ jobs:
--var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET"
--var NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY"
--var NR_BROWSER_KEY="$NR_BROWSER_KEY"
--var COMMIT_HASH="$COMMIT_HASH"
--var LOGIN_PEM="$LOGIN_PEM"
--var LOGIN_DOT_GOV_CLIENT_ID="$LOGIN_DOT_GOV_CLIENT_ID"
--var LOGIN_DOT_GOV_USER_INFO_URL="$LOGIN_DOT_GOV_USER_INFO_URL"
--var LOGIN_DOT_GOV_ACCESS_TOKEN_URL="$LOGIN_DOT_GOV_ACCESS_TOKEN_URL"
--var LOGIN_DOT_GOV_LOGOUT_URL="$LOGIN_DOT_GOV_LOGOUT_URL"
--var LOGIN_DOT_GOV_BASE_LOGOUT_URL="$LOGIN_DOT_GOV_BASE_LOGOUT_URL"
--var LOGIN_DOT_GOV_SIGNOUT_REDIRECT="$LOGIN_DOT_GOV_SIGNOUT_REDIRECT"
--var LOGIN_DOT_GOV_INITIAL_SIGNIN_URL="$LOGIN_DOT_GOV_INITIAL_SIGNIN_URL"
- name: Check for changes to egress config
id: changed-egress-config

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2
@@ -54,8 +54,15 @@ jobs:
ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }}
NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }}
COMMIT_HASH: ${{ github.sha }}
LOGIN_PEM: ${{ secrets.LOGIN_PEM }}
LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov"
LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo"
LOGIN_DOT_GOV_ACCESS_TOKEN_URL: "https://secure.login.gov/api/openid_connect/token"
LOGIN_DOT_GOV_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&post_logout_redirect_uri=https://beta.notify.gov/sign-out"
LOGIN_DOT_GOV_BASE_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?"
LOGIN_DOT_GOV_SIGNOUT_REDIRECT: "https://beta.notify.gov/sign-out"
LOGIN_DOT_GOV_INITIAL_SIGNIN_URL: "https://secure.login.gov/openid_connect/authorize?acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&nonce=NONCE&prompt=select_account&redirect_uri=https://beta.notify.gov/sign-in&response_type=code&scope=openid+email&state=STATE"
with:
cf_username: ${{ secrets.CLOUDGOV_USERNAME }}
cf_password: ${{ secrets.CLOUDGOV_PASSWORD }}
@@ -69,7 +76,15 @@ jobs:
--var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET"
--var NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY"
--var NR_BROWSER_KEY="$NR_BROWSER_KEY"
--var COMMIT_HASH="$COMMIT_HASH"
--var LOGIN_PEM="$LOGIN_PEM"
--var LOGIN_DOT_GOV_CLIENT_ID="$LOGIN_DOT_GOV_CLIENT_ID"
--var LOGIN_DOT_GOV_USER_INFO_URL="$LOGIN_DOT_GOV_USER_INFO_URL"
--var LOGIN_DOT_GOV_ACCESS_TOKEN_URL="$LOGIN_DOT_GOV_ACCESS_TOKEN_URL"
--var LOGIN_DOT_GOV_LOGOUT_URL="$LOGIN_DOT_GOV_LOGOUT_URL"
--var LOGIN_DOT_GOV_BASE_LOGOUT_URL="$LOGIN_DOT_GOV_BASE_LOGOUT_URL"
--var LOGIN_DOT_GOV_SIGNOUT_REDIRECT="$LOGIN_DOT_GOV_SIGNOUT_REDIRECT"
--var LOGIN_DOT_GOV_INITIAL_SIGNIN_URL="$LOGIN_DOT_GOV_INITIAL_SIGNIN_URL"
- name: Check for changes to egress config
id: changed-egress-config

View File

@@ -17,7 +17,7 @@ jobs:
environment: staging
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2
@@ -60,14 +60,15 @@ jobs:
ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }}
NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }}
COMMIT_HASH: ${{ github.sha }}
LOGIN_PEM: ${{ secrets.LOGIN_PEM }}
LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov"
LOGIN_DOT_GOV_USER_INFO_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo"
LOGIN_DOT_GOV_ACCESS_TOKEN_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/token"
LOGIN_DOT_GOV_LOGOUT_URL: "https://idp.int.identitysandbox.gov/openid_connect/logout?client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&post_logout_redirect_uri=https://notify-staging.app.cloud.gov/sign-out"
LOGIN_DOT_GOV_BASE_LOGOUT_URL: "https://idp.int.identitysandbox.gov/openid_connect/logout?"
LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo"
LOGIN_DOT_GOV_ACCESS_TOKEN_URL: "https://secure.login.gov/api/openid_connect/token"
LOGIN_DOT_GOV_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&post_logout_redirect_uri=https://notify-staging.app.cloud.gov/sign-out"
LOGIN_DOT_GOV_BASE_LOGOUT_URL: "https://secure.login.gov/openid_connect/logout?"
LOGIN_DOT_GOV_SIGNOUT_REDIRECT: "https://notify-staging.app.cloud.gov/sign-out"
LOGIN_DOT_GOV_INITIAL_SIGNIN_URL: "https://idp.int.identitysandbox.gov/openid_connect/authorize?acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&nonce=01234567890123456789012345&prompt=select_account&redirect_uri=https://notify-staging.app.cloud.gov/sign-in&response_type=code&scope=openid+email&state=abcdefghijklmnopabcdefghijklmnop"
LOGIN_DOT_GOV_INITIAL_SIGNIN_URL: "https://secure.login.gov/openid_connect/authorize?acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&client_id=urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov&nonce=NONCE&prompt=select_account&redirect_uri=https://notify-staging.app.cloud.gov/sign-in&response_type=code&scope=openid+email&state=STATEE"
with:
cf_username: ${{ secrets.CLOUDGOV_USERNAME }}
cf_password: ${{ secrets.CLOUDGOV_PASSWORD }}
@@ -81,6 +82,7 @@ jobs:
--var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET"
--var NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY"
--var NR_BROWSER_KEY="$NR_BROWSER_KEY"
--var COMMIT_HASH="$COMMIT_HASH"
--var LOGIN_PEM="$LOGIN_PEM"
--var LOGIN_DOT_GOV_CLIENT_ID="$LOGIN_DOT_GOV_CLIENT_ID"
--var LOGIN_DOT_GOV_USER_INFO_URL="$LOGIN_DOT_GOV_USER_INFO_URL"

View File

@@ -13,7 +13,7 @@ jobs:
environment: staging
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check for drift
uses: dflook/terraform-check@v1
@@ -31,7 +31,7 @@ jobs:
environment: demo
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: 'production'
@@ -51,7 +51,7 @@ jobs:
environment: production
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: 'production'

View File

@@ -16,7 +16,7 @@ jobs:
environment: demo
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Terraform format
id: format

View File

@@ -16,7 +16,7 @@ jobs:
environment: production
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Terraform format
id: format

View File

@@ -16,7 +16,7 @@ jobs:
environment: staging
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Terraform format
id: format

View File

@@ -4,3 +4,6 @@
##
export NEW_RELIC_PROXY_HOST=$egress_proxy
export http_proxy=$egress_proxy
export https_proxy=$egress_proxy
export no_proxy="apps.internal"

View File

@@ -17,6 +17,7 @@ NVMSH := $(shell [ -f "$(HOME)/.nvm/nvm.sh" ] && echo "$(HOME)/.nvm/nvm.sh" || e
bootstrap: generate-version-file ## Set up everything to run the app
poetry self update
poetry self add poetry-dotenv-plugin
poetry lock --no-update
poetry install --sync --no-root
poetry run playwright install --with-deps
poetry run pre-commit install
@@ -80,8 +81,8 @@ dead-code:
.PHONY: e2e-test
e2e-test: export NEW_RELIC_ENVIRONMENT=test
e2e-test: ## Run end-to-end integration tests
poetry run pytest -v --browser chromium --browser firefox --browser webkit tests/end_to_end
e2e-test: ## Run end-to-end integration tests; note that --browser webkit isn't currently working
poetry run pytest -v --browser chromium --browser firefox tests/end_to_end
.PHONY: js-lint
js-lint: ## Run javascript linting scanners

View File

@@ -1,3 +1,5 @@
![notify-logo](https://github.com/GSA/notifications-admin/assets/4156602/31b74039-4d87-4f89-a35e-71e9f3152342)
# Notify.gov Admin UI
This is the Notify front-end for government users and admins. To see it in
@@ -183,12 +185,12 @@ session to make the changes take effect.
Now we're ready to install the Python version we need with `pyenv`, like so:
```sh
pyenv install 3.9
pyenv install 3.12
```
This will install the latest version of Python 3.9.
This will install the latest version of Python 3.12.
_NOTE: This project currently runs on Python 3.9.x._
_NOTE: This project currently runs on Python 3.12.x._
#### [API Step] Python Dependency Installation
@@ -232,7 +234,7 @@ Once all of pre-requisites for the project are installed and you have a
cloud.gov account, you can now set up the admin project and get things running
locally!
First, clone the respository in the directory of your choosing on your machine:
First, clone the repository in the directory of your choosing on your machine:
```sh
git clone git@github.com:GSA/notifications-admin.git
@@ -240,12 +242,12 @@ git clone git@github.com:GSA/notifications-admin.git
Now go into the project directory (`notifications-admin` by default), create a
virtual environment, and set the local Python version to point to the virtual
environment (assumes version Python `3.9.18` is what is installed on your
environment (assumes version Python `3.12.2` is what is installed on your
machine):
```sh
cd notifications-admin
pyenv virtualenv 3.9.18 notify-admin
pyenv virtualenv 3.12.2 notify-admin
pyenv local notify-admin
```
@@ -272,6 +274,39 @@ In addition to some infrastructure setup, this will also create a local `.env`
file for you in the project's root directory, which will include a handful of
project-specific environment variables.
#### Upgrading Python in existing projects
If you're upgrading an existing project to a newer version of Python, you can
follow these steps to get yourself up-to-date.
First, use `pyenv` to install the newer version of Python you'd like to use;
we'll use `3.12` in our example here since we recently upgraded to this version:
```sh
pyenv install 3.12
```
Next, delete the virtual environment you previously had set up. If you followed
the instructions above with the first-time set up, you can do this with `pyenv`:
```sh
pyenv virtualenv-delete notify-admin
```
Now, make sure you are in your project directory and recreate the same virtual
environment with the newer version of Python you just installed:
```sh
cd notifications-admin
pyenv virtualenv 3.12.2 notify-admin
pyenv local notify-admin
```
At this point, proceed with the rest of the instructions here in the README and
you'll be set with an upgraded version of Python.
_If you're not sure about the details of your current virtual environment, you can run `poetry env info` to get more information. If you've been using `pyenv` for everything, you can also see all available virtual environments with `pyenv virtualenvs`._
#### Updating the .env file for E2E tests
With the newly created `.env` file in place, you'll need to make one more
@@ -378,52 +413,6 @@ You can do this by going through these steps:
- Make a new PR with the change
- Have the PR get reviewed and merged
### Python dependency management
We're using [`Poetry`](https://python-poetry.org/) for managing our Python
dependencies and local virtual environments. When it comes to managing the
Python dependencies, there are a couple of things to bear in mind.
For situations where you manually manipulate the `pyproject.toml` file, you
should use the `make py-lock` command to sync the `poetry.lock` file. This will
ensure that you don't inadvertently bring in other transitive dependency updates
that have not been fully tested with the project yet.
If you're just trying to update a dependency to a newer (or the latest) version,
you should let Poetry take care of that for you by running the following:
```sh
poetry update <dependency> [<dependency>...]
```
You can specify more than one dependency together. With this command, Poetry
will do the following for you:
- Find the latest compatible version(s) of the specified dependency/dependencies
- Install the new versions
- Update and sync the `poetry.lock` file
In either situation, once you are finished and have verified the dependency
changes are working, please be sure to commit both the `pyproject.toml` and
`poetry.lock` files.
### Keeping the notification-utils dependency up-to-date
The `notifications-utils` dependency references the other repository we have at
https://github.com/GSA/notifications-utils - this dependency requires a bit of
extra legwork to ensure it stays up-to-date.
Whenever a PR is merged in the `notifications-utils` repository, we need to make
sure the changes are pulled in here and committed to this repository as well.
You can do this by going through these steps:
- Make sure your local `main` branch is up-to-date
- Create a new branch to work in
- Run `make update-utils`
- Commit the updated `poetry.lock` file and push the changes
- Make a new PR with the change
- Have the PR get reviewed and merged
## Known Installation Issues
### Python Installation Errors

View File

@@ -21,7 +21,6 @@ from flask_login import LoginManager, current_user
from flask_talisman import Talisman
from flask_wtf import CSRFProtect
from flask_wtf.csrf import CSRFError
from govuk_frontend_jinja.flask_ext import init_govuk_frontend
from itsdangerous import BadSignature
from notifications_python_client.errors import HTTPError
from notifications_utils import logging, request_helper
@@ -53,7 +52,7 @@ from app.formatters import (
format_datetime_human,
format_datetime_normal,
format_datetime_relative,
format_datetime_short,
format_datetime_table,
format_day_of_week,
format_delta,
format_delta_days,
@@ -113,6 +112,7 @@ from app.notify_client.template_statistics_api_client import template_statistics
from app.notify_client.upload_api_client import upload_api_client
from app.notify_client.user_api_client import user_api_client
from app.url_converters import SimpleDateTypeConverter, TemplateTypeConverter
from app.utils.govuk_frontend_jinja.flask_ext import init_govuk_frontend
login_manager = LoginManager()
csrf = CSRFProtect()
@@ -380,6 +380,10 @@ def load_service_before_request():
request_ctx.service = Service(
service_api_client.get_service(service_id)["data"]
)
stats = service_api_client.get_service_statistics(
service_id, limit_days=7
)
request_ctx.service.stats = stats
except HTTPError as exc:
# if service id isn't real, then 404 rather than 500ing later because we expect service to be set
if exc.status_code == 404:
@@ -547,7 +551,7 @@ def add_template_filters(application):
format_datetime,
format_datetime_24h,
format_datetime_normal,
format_datetime_short,
format_datetime_table,
valid_phone_number,
linkable_name,
format_date,

View File

@@ -22,7 +22,7 @@
<link rel="stylesheet" media="screen" href="/static/stylesheets/main.css?d077f86473501ab244de0b30600536ee" />
<link rel="stylesheet" media="print" href="/static/stylesheets/print.css?28010888ca5719dc83d7c2c80f6ed2b2" />
<meta property="og:image" content="/static/images/usa-opengraph-image.png">
<meta property="og:image" content="/static/images/notify-og-image.png">
</head>
<body class="usa-template__body">
@@ -107,4 +107,4 @@
</body>
</html>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,7 @@
<svg width="187" height="230" viewBox="0 0 187 230" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M89.1324 230V203.125H57.936C60.0752 226.499 79.7735 230 89.1324 230Z" fill="#2491FF"/>
<path d="M89.1324 230V203.125H121.22C119.02 226.499 98.7587 230 89.1324 230Z" fill="#005EA2"/>
<path d="M71.4869 19.5185C71.4869 3.35574 82.3456 0 89.1324 0V194.166H0V174.861L22.1703 153.759V87.3122C22.1703 47.8033 53.8415 24.1578 71.4869 19.5185Z" fill="#2491FF"/>
<path d="M89.1324 0C95.9192 0 106.778 3.35574 106.778 19.5185C112.193 20.9422 118.928 24.1557 125.664 29.0681C118.405 36.2889 113.911 46.2873 113.911 57.3353C113.911 79.3543 131.761 97.2043 153.78 97.2043C154.557 97.2043 155.293 97.2481 156.058 97.2043L156.094 153.759L178.265 174.861V194.166H89.1324V0Z" fill="#005EA2"/>
<path d="M186.435 57.1535C186.435 74.9784 171.985 89.4283 154.16 89.4283C136.335 89.4283 121.885 74.9784 121.885 57.1535C121.885 39.3286 136.335 24.8786 154.16 24.8786C171.985 24.8786 186.435 39.3286 186.435 57.1535Z" fill="#D54309"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,17 @@
<svg width="1596" height="400" viewBox="0 0 1596 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M155.013 400V353.26H100.758C104.479 393.912 138.736 400 155.013 400Z" fill="#58B4FF"/>
<path d="M155.013 400V353.26H210.818C206.991 393.912 171.754 400 155.013 400Z" fill="#0076D6"/>
<path d="M124.325 33.9452C124.325 5.83608 143.21 0 155.013 0V337.68H0V304.105L38.5571 267.407V151.847C38.5571 83.1361 93.6374 42.0136 124.325 33.9452Z" fill="#58B4FF"/>
<path d="M155.013 0C166.816 0 185.701 5.83608 185.701 33.9452C195.118 36.4212 206.832 42.0098 218.547 50.5533C205.922 63.1111 198.106 80.4997 198.106 99.7136C198.106 138.008 229.15 169.051 267.444 169.051C268.795 169.051 270.074 169.127 271.406 169.051L271.469 267.407L310.026 304.105V337.68H155.013V0Z" fill="#0076D6"/>
<path d="M324.234 99.3973C324.234 130.397 299.104 155.528 268.104 155.528C237.104 155.528 211.974 130.397 211.974 99.3973C211.974 68.3975 237.104 43.2672 268.104 43.2672C299.104 43.2672 324.234 68.3975 324.234 99.3973Z" fill="#D54309"/>
<path d="M416.684 290.469C414.747 290.469 413.25 289.94 412.194 288.884C411.137 287.651 410.609 286.154 410.609 284.393V111.909C410.609 109.972 411.137 108.475 412.194 107.418C413.25 106.186 414.747 105.569 416.684 105.569H428.835C430.948 105.569 432.532 106.098 433.589 107.154C434.646 108.035 435.262 108.739 435.438 109.267L523.133 243.98V111.909C523.133 109.972 523.662 108.475 524.718 107.418C525.775 106.186 527.271 105.569 529.208 105.569H541.887C543.824 105.569 545.321 106.186 546.378 107.418C547.61 108.475 548.227 109.972 548.227 111.909V284.129C548.227 285.89 547.61 287.387 546.378 288.62C545.321 289.852 543.912 290.469 542.151 290.469H529.473C527.536 290.469 526.039 289.94 524.982 288.884C524.102 287.827 523.485 287.123 523.133 286.771L435.702 153.379V284.393C435.702 286.154 435.086 287.651 433.853 288.884C432.797 289.94 431.3 290.469 429.363 290.469H416.684Z" fill="#EDEFF0"/>
<path d="M636.275 293.11C622.892 293.11 611.71 290.557 602.729 285.45C593.748 280.343 586.88 273.299 582.126 264.319C577.371 255.162 574.73 244.772 574.201 233.15C574.025 230.156 573.937 226.37 573.937 221.792C573.937 217.037 574.025 213.251 574.201 210.434C574.73 198.635 577.371 188.246 582.126 179.265C587.056 170.284 594.012 163.24 602.993 158.133C611.974 153.027 623.068 150.473 636.275 150.473C649.482 150.473 660.576 153.027 669.557 158.133C678.537 163.24 685.405 170.284 690.16 179.265C695.09 188.246 697.82 198.635 698.348 210.434C698.524 213.251 698.612 217.037 698.612 221.792C698.612 226.37 698.524 230.156 698.348 233.15C697.82 244.772 695.178 255.162 690.424 264.319C685.669 273.299 678.802 280.343 669.821 285.45C660.84 290.557 649.658 293.11 636.275 293.11ZM636.275 272.771C647.193 272.771 655.909 269.337 662.425 262.47C668.94 255.426 672.462 245.212 672.99 231.829C673.167 229.188 673.255 225.842 673.255 221.792C673.255 217.742 673.167 214.396 672.99 211.754C672.462 198.371 668.94 188.246 662.425 181.378C655.909 174.334 647.193 170.812 636.275 170.812C625.357 170.812 616.552 174.334 609.861 181.378C603.345 188.246 599.911 198.371 599.559 211.754C599.383 214.396 599.295 217.742 599.295 221.792C599.295 225.842 599.383 229.188 599.559 231.829C599.911 245.212 603.345 255.426 609.861 262.47C616.552 269.337 625.357 272.771 636.275 272.771Z" fill="#EDEFF0"/>
<path d="M781.377 290.469C771.516 290.469 763.504 288.62 757.341 284.922C751.177 281.048 746.687 275.677 743.869 268.809C741.052 261.765 739.643 253.489 739.643 243.98V174.246H719.04C717.279 174.246 715.782 173.718 714.549 172.661C713.493 171.429 712.965 169.932 712.965 168.171V159.19C712.965 157.429 713.493 156.02 714.549 154.964C715.782 153.731 717.279 153.115 719.04 153.115H739.643V109.003C739.643 107.242 740.171 105.833 741.228 104.777C742.461 103.544 743.957 102.928 745.718 102.928H758.133C759.894 102.928 761.303 103.544 762.359 104.777C763.592 105.833 764.208 107.242 764.208 109.003V153.115H796.962C798.723 153.115 800.132 153.731 801.188 154.964C802.421 156.02 803.037 157.429 803.037 159.19V168.171C803.037 169.932 802.421 171.429 801.188 172.661C800.132 173.718 798.723 174.246 796.962 174.246H764.208V242.131C764.208 250.407 765.617 256.923 768.434 261.677C771.252 266.432 776.271 268.809 783.491 268.809H799.603C801.364 268.809 802.773 269.425 803.83 270.658C805.062 271.715 805.678 273.123 805.678 274.884V284.393C805.678 286.154 805.062 287.651 803.83 288.884C802.773 289.94 801.364 290.469 799.603 290.469H781.377Z" fill="#EDEFF0"/>
<path d="M834.371 290.469C832.61 290.469 831.113 289.94 829.88 288.884C828.824 287.651 828.296 286.154 828.296 284.393V159.19C828.296 157.429 828.824 156.02 829.88 154.964C831.113 153.731 832.61 153.115 834.371 153.115H847.05C848.811 153.115 850.219 153.731 851.276 154.964C852.333 156.02 852.861 157.429 852.861 159.19V284.393C852.861 286.154 852.333 287.651 851.276 288.884C850.219 289.94 848.811 290.469 847.05 290.469H834.371ZM832.258 127.493C830.497 127.493 829 126.965 827.767 125.908C826.711 124.675 826.182 123.179 826.182 121.418V107.154C826.182 105.393 826.711 103.984 827.767 102.928C829 101.695 830.497 101.079 832.258 101.079H848.899C850.66 101.079 852.068 101.695 853.125 102.928C854.358 103.984 854.974 105.393 854.974 107.154V121.418C854.974 123.179 854.358 124.675 853.125 125.908C852.068 126.965 850.66 127.493 848.899 127.493H832.258Z" fill="#EDEFF0"/>
<path d="M912.078 290.469C910.317 290.469 908.82 289.94 907.588 288.884C906.531 287.651 906.003 286.154 906.003 284.393V174.246H883.551C881.79 174.246 880.293 173.718 879.06 172.661C878.004 171.429 877.476 169.932 877.476 168.171V159.19C877.476 157.429 878.004 156.02 879.06 154.964C880.293 153.731 881.79 153.115 883.551 153.115H906.003V139.908C906.003 130.927 907.5 123.091 910.493 116.399C913.487 109.531 918.242 104.249 924.757 100.551C931.449 96.8525 940.341 95.0036 951.435 95.0036H967.284C969.045 95.0036 970.454 95.6199 971.51 96.8525C972.567 97.9091 973.095 99.3179 973.095 101.079V110.06C973.095 111.821 972.567 113.317 971.51 114.55C970.454 115.607 969.045 116.135 967.284 116.135H951.964C943.687 116.135 938.052 118.336 935.059 122.738C932.065 126.965 930.568 133.128 930.568 141.228V153.115H964.642C966.403 153.115 967.812 153.731 968.869 154.964C969.925 156.02 970.454 157.429 970.454 159.19V168.171C970.454 169.932 969.925 171.429 968.869 172.661C967.812 173.718 966.403 174.246 964.642 174.246H930.568V284.393C930.568 286.154 929.952 287.651 928.719 288.884C927.663 289.94 926.254 290.469 924.493 290.469H912.078Z" fill="#EDEFF0"/>
<path d="M1017.94 340.656C1016.53 340.656 1015.3 340.127 1014.24 339.071C1013.18 338.014 1012.65 336.782 1012.65 335.373C1012.65 334.668 1012.74 333.964 1012.92 333.26C1013.09 332.555 1013.45 331.675 1013.98 330.618L1034.31 282.28L983.863 163.152C982.982 161.039 982.542 159.542 982.542 158.662C982.542 157.077 983.071 155.756 984.127 154.7C985.184 153.643 986.504 153.115 988.089 153.115H1001.03C1002.79 153.115 1004.2 153.555 1005.26 154.435C1006.31 155.316 1007.02 156.373 1007.37 157.605L1047.52 253.753L1088.73 157.605C1089.26 156.373 1089.96 155.316 1090.84 154.435C1091.9 153.555 1093.39 153.115 1095.33 153.115H1107.75C1109.33 153.115 1110.65 153.643 1111.71 154.7C1112.76 155.756 1113.29 156.989 1113.29 158.398C1113.29 159.278 1112.85 160.863 1111.97 163.152L1036.96 336.165C1036.43 337.398 1035.63 338.454 1034.58 339.335C1033.7 340.215 1032.29 340.656 1030.35 340.656H1017.94Z" fill="#EDEFF0"/>
<path d="M1128.65 290.469C1126.89 290.469 1125.39 289.94 1124.16 288.884C1123.1 287.651 1122.57 286.154 1122.57 284.393V265.375C1122.57 263.614 1123.1 262.205 1124.16 261.149C1125.39 259.916 1126.89 259.3 1128.65 259.3H1147.67C1149.43 259.3 1150.84 259.916 1151.89 261.149C1153.13 262.205 1153.74 263.614 1153.74 265.375V284.393C1153.74 286.154 1153.13 287.651 1151.89 288.884C1150.84 289.94 1149.43 290.469 1147.67 290.469H1128.65Z" fill="#EDEFF0"/>
<path d="M1244.66 348.58C1232.68 348.58 1222.82 346.995 1215.07 343.825C1207.5 340.656 1201.51 336.782 1197.11 332.203C1192.89 327.801 1189.8 323.31 1187.87 318.732C1186.11 314.329 1185.14 310.808 1184.96 308.166C1184.79 306.405 1185.31 304.908 1186.55 303.676C1187.96 302.443 1189.45 301.827 1191.04 301.827H1203.72C1205.3 301.827 1206.62 302.179 1207.68 302.883C1208.73 303.588 1209.61 305.084 1210.32 307.374C1211.38 310.015 1212.96 312.921 1215.07 316.09C1217.19 319.436 1220.44 322.254 1224.85 324.543C1229.25 327.008 1235.41 328.241 1243.34 328.241C1251.61 328.241 1258.57 327.096 1264.2 324.807C1269.84 322.694 1274.07 318.82 1276.88 313.185C1279.88 307.726 1281.37 300.154 1281.37 290.469V272.507C1277.15 277.966 1271.6 282.544 1264.73 286.242C1257.86 289.764 1249.24 291.525 1238.85 291.525C1228.99 291.525 1220.53 289.852 1213.49 286.507C1206.45 282.985 1200.63 278.318 1196.06 272.507C1191.65 266.52 1188.31 259.74 1186.02 252.168C1183.91 244.596 1182.67 236.672 1182.32 228.395C1182.14 223.465 1182.14 218.622 1182.32 213.867C1182.67 205.591 1183.91 197.667 1186.02 190.095C1188.31 182.523 1191.65 175.743 1196.06 169.756C1200.63 163.769 1206.45 159.102 1213.49 155.756C1220.53 152.234 1228.99 150.473 1238.85 150.473C1249.41 150.473 1258.13 152.498 1265 156.549C1272.04 160.423 1277.76 165.177 1282.17 170.812V159.454C1282.17 157.693 1282.69 156.196 1283.75 154.964C1284.98 153.731 1286.48 153.115 1288.24 153.115H1300.39C1302.15 153.115 1303.65 153.731 1304.88 154.964C1306.11 156.196 1306.73 157.693 1306.73 159.454V287.563C1306.73 299.361 1304.71 309.839 1300.66 318.996C1296.78 328.153 1290.27 335.373 1281.11 340.656C1272.13 345.938 1259.98 348.58 1244.66 348.58ZM1244.13 270.394C1252.93 270.394 1259.98 268.369 1265.26 264.319C1270.72 260.268 1274.68 255.162 1277.15 248.998C1279.79 242.835 1281.2 236.584 1281.37 230.244C1281.55 227.779 1281.64 224.785 1281.64 221.263C1281.64 217.565 1281.55 214.484 1281.37 212.018C1281.2 205.679 1279.79 199.428 1277.15 193.264C1274.68 187.101 1270.72 181.994 1265.26 177.944C1259.98 173.894 1252.93 171.869 1244.13 171.869C1235.32 171.869 1228.28 173.894 1223 177.944C1217.72 181.818 1213.93 187.013 1211.64 193.529C1209.35 199.868 1208.03 206.736 1207.68 214.132C1207.5 218.71 1207.5 223.377 1207.68 228.131C1208.03 235.527 1209.35 242.483 1211.64 248.998C1213.93 255.338 1217.72 260.533 1223 264.583C1228.28 268.457 1235.32 270.394 1244.13 270.394Z" fill="#EDEFF0"/>
<path d="M1394.34 293.11C1380.96 293.11 1369.78 290.557 1360.8 285.45C1351.81 280.343 1344.95 273.299 1340.19 264.319C1335.44 255.162 1332.8 244.772 1332.27 233.15C1332.09 230.156 1332 226.37 1332 221.792C1332 217.037 1332.09 213.251 1332.27 210.434C1332.8 198.635 1335.44 188.246 1340.19 179.265C1345.12 170.284 1352.08 163.24 1361.06 158.133C1370.04 153.027 1381.13 150.473 1394.34 150.473C1407.55 150.473 1418.64 153.027 1427.62 158.133C1436.6 163.24 1443.47 170.284 1448.23 179.265C1453.16 188.246 1455.89 198.635 1456.42 210.434C1456.59 213.251 1456.68 217.037 1456.68 221.792C1456.68 226.37 1456.59 230.156 1456.42 233.15C1455.89 244.772 1453.25 255.162 1448.49 264.319C1443.74 273.299 1436.87 280.343 1427.89 285.45C1418.91 290.557 1407.72 293.11 1394.34 293.11ZM1394.34 272.771C1405.26 272.771 1413.98 269.337 1420.49 262.47C1427.01 255.426 1430.53 245.212 1431.06 231.829C1431.23 229.188 1431.32 225.842 1431.32 221.792C1431.32 217.742 1431.23 214.396 1431.06 211.754C1430.53 198.371 1427.01 188.246 1420.49 181.378C1413.98 174.334 1405.26 170.812 1394.34 170.812C1383.42 170.812 1374.62 174.334 1367.93 181.378C1361.41 188.246 1357.98 198.371 1357.63 211.754C1357.45 214.396 1357.36 217.742 1357.36 221.792C1357.36 225.842 1357.45 229.188 1357.63 231.829C1357.98 245.212 1361.41 255.426 1367.93 262.47C1374.62 269.337 1383.42 272.771 1394.34 272.771Z" fill="#EDEFF0"/>
<path d="M1524.74 290.469C1522.1 290.469 1519.98 289.852 1518.4 288.62C1516.99 287.387 1515.85 285.802 1514.97 283.865L1466.1 161.303C1465.75 160.423 1465.57 159.542 1465.57 158.662C1465.57 157.077 1466.1 155.756 1467.16 154.7C1468.21 153.643 1469.53 153.115 1471.12 153.115H1483.8C1485.73 153.115 1487.23 153.643 1488.29 154.7C1489.34 155.756 1489.96 156.725 1490.14 157.605L1530.55 261.677L1570.7 157.605C1571.05 156.725 1571.67 155.756 1572.55 154.7C1573.61 153.643 1575.1 153.115 1577.04 153.115H1589.98C1591.39 153.115 1592.62 153.643 1593.68 154.7C1594.91 155.756 1595.53 157.077 1595.53 158.662C1595.53 159.542 1595.35 160.423 1595 161.303L1545.87 283.865C1545.17 285.802 1544.02 287.387 1542.44 288.62C1541.03 289.852 1538.91 290.469 1536.1 290.469H1524.74Z" fill="#EDEFF0"/>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,17 @@
<svg width="1596" height="400" viewBox="0 0 1596 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M155.013 400V353.26H100.759C104.479 393.912 138.737 400 155.013 400Z" fill="#2491FF"/>
<path d="M155.013 400V353.26H210.818C206.992 393.912 171.755 400 155.013 400Z" fill="#005EA2"/>
<path d="M124.326 33.9452C124.326 5.83608 143.21 0 155.014 0V337.68H0V304.105L38.5573 267.407V151.847C38.5573 83.1361 93.6378 42.0136 124.326 33.9452Z" fill="#2491FF"/>
<path d="M155.014 0C166.817 0 185.702 5.83608 185.702 33.9452C195.119 36.4212 206.833 42.0098 218.548 50.5533C205.923 63.1111 198.107 80.4997 198.107 99.7136C198.107 138.008 229.151 169.051 267.445 169.051C268.796 169.051 270.075 169.127 271.407 169.051L271.47 267.407L310.027 304.105V337.68H155.014V0Z" fill="#005EA2"/>
<path d="M324.236 99.3973C324.236 130.397 299.105 155.528 268.105 155.528C237.105 155.528 211.975 130.397 211.975 99.3973C211.975 68.3975 237.105 43.2672 268.105 43.2672C299.105 43.2672 324.236 68.3975 324.236 99.3973Z" fill="#D54309"/>
<path d="M416.686 290.469C414.749 290.469 413.252 289.94 412.195 288.884C411.139 287.651 410.61 286.154 410.61 284.393V111.909C410.61 109.972 411.139 108.475 412.195 107.418C413.252 106.186 414.749 105.569 416.686 105.569H428.836C430.95 105.569 432.534 106.098 433.591 107.154C434.647 108.035 435.264 108.739 435.44 109.267L523.135 243.98V111.909C523.135 109.972 523.664 108.475 524.72 107.418C525.777 106.186 527.274 105.569 529.211 105.569H541.89C543.827 105.569 545.323 106.186 546.38 107.418C547.613 108.475 548.229 109.972 548.229 111.909V284.129C548.229 285.89 547.613 287.387 546.38 288.62C545.323 289.852 543.915 290.469 542.154 290.469H529.475C527.538 290.469 526.041 289.94 524.984 288.884C524.104 287.827 523.488 287.123 523.135 286.771L435.704 153.379V284.393C435.704 286.154 435.088 287.651 433.855 288.884C432.798 289.94 431.302 290.469 429.365 290.469H416.686Z" fill="#2D2E2F"/>
<path d="M636.277 293.11C622.894 293.11 611.712 290.557 602.731 285.45C593.75 280.343 586.883 273.299 582.128 264.319C577.373 255.162 574.732 244.772 574.204 233.15C574.028 230.156 573.94 226.37 573.94 221.792C573.94 217.037 574.028 213.251 574.204 210.434C574.732 198.635 577.373 188.246 582.128 179.265C587.059 170.284 594.014 163.24 602.995 158.133C611.976 153.027 623.07 150.473 636.277 150.473C649.485 150.473 660.579 153.027 669.559 158.133C678.54 163.24 685.408 170.284 690.163 179.265C695.093 188.246 697.823 198.635 698.351 210.434C698.527 213.251 698.615 217.037 698.615 221.792C698.615 226.37 698.527 230.156 698.351 233.15C697.823 244.772 695.181 255.162 690.427 264.319C685.672 273.299 678.804 280.343 669.824 285.45C660.843 290.557 649.661 293.11 636.277 293.11ZM636.277 272.771C647.195 272.771 655.912 269.337 662.428 262.47C668.943 255.426 672.465 245.212 672.993 231.829C673.169 229.188 673.257 225.842 673.257 221.792C673.257 217.742 673.169 214.396 672.993 211.754C672.465 198.371 668.943 188.246 662.428 181.378C655.912 174.334 647.195 170.812 636.277 170.812C625.359 170.812 616.555 174.334 609.863 181.378C603.348 188.246 599.914 198.371 599.562 211.754C599.385 214.396 599.297 217.742 599.297 221.792C599.297 225.842 599.385 229.188 599.562 231.829C599.914 245.212 603.348 255.426 609.863 262.47C616.555 269.337 625.359 272.771 636.277 272.771Z" fill="#2D2E2F"/>
<path d="M781.381 290.469C771.519 290.469 763.507 288.62 757.344 284.922C751.18 281.048 746.69 275.677 743.872 268.809C741.055 261.765 739.646 253.489 739.646 243.98V174.246H719.043C717.282 174.246 715.785 173.718 714.552 172.661C713.496 171.429 712.968 169.932 712.968 168.171V159.19C712.968 157.429 713.496 156.02 714.552 154.964C715.785 153.731 717.282 153.115 719.043 153.115H739.646V109.003C739.646 107.242 740.174 105.833 741.231 104.777C742.464 103.544 743.96 102.928 745.721 102.928H758.136C759.897 102.928 761.306 103.544 762.362 104.777C763.595 105.833 764.211 107.242 764.211 109.003V153.115H796.965C798.726 153.115 800.135 153.731 801.191 154.964C802.424 156.02 803.04 157.429 803.04 159.19V168.171C803.04 169.932 802.424 171.429 801.191 172.661C800.135 173.718 798.726 174.246 796.965 174.246H764.211V242.131C764.211 250.407 765.62 256.923 768.438 261.677C771.255 266.432 776.274 268.809 783.494 268.809H799.607C801.368 268.809 802.776 269.425 803.833 270.658C805.066 271.715 805.682 273.123 805.682 274.884V284.393C805.682 286.154 805.066 287.651 803.833 288.884C802.776 289.94 801.368 290.469 799.607 290.469H781.381Z" fill="#2D2E2F"/>
<path d="M834.374 290.469C832.613 290.469 831.117 289.94 829.884 288.884C828.827 287.651 828.299 286.154 828.299 284.393V159.19C828.299 157.429 828.827 156.02 829.884 154.964C831.117 153.731 832.613 153.115 834.374 153.115H847.053C848.814 153.115 850.223 153.731 851.28 154.964C852.336 156.02 852.864 157.429 852.864 159.19V284.393C852.864 286.154 852.336 287.651 851.28 288.884C850.223 289.94 848.814 290.469 847.053 290.469H834.374ZM832.261 127.493C830.5 127.493 829.004 126.965 827.771 125.908C826.714 124.675 826.186 123.179 826.186 121.418V107.154C826.186 105.393 826.714 103.984 827.771 102.928C829.004 101.695 830.5 101.079 832.261 101.079H848.902C850.663 101.079 852.072 101.695 853.129 102.928C854.361 103.984 854.978 105.393 854.978 107.154V121.418C854.978 123.179 854.361 124.675 853.129 125.908C852.072 126.965 850.663 127.493 848.902 127.493H832.261Z" fill="#2D2E2F"/>
<path d="M912.082 290.469C910.321 290.469 908.824 289.94 907.592 288.884C906.535 287.651 906.007 286.154 906.007 284.393V174.246H883.555C881.794 174.246 880.297 173.718 879.064 172.661C878.008 171.429 877.479 169.932 877.479 168.171V159.19C877.479 157.429 878.008 156.02 879.064 154.964C880.297 153.731 881.794 153.115 883.555 153.115H906.007V139.908C906.007 130.927 907.504 123.091 910.497 116.399C913.491 109.531 918.245 104.249 924.761 100.551C931.453 96.8525 940.345 95.0035 951.439 95.0035H967.288C969.049 95.0035 970.458 95.6199 971.514 96.8525C972.571 97.9091 973.099 99.3179 973.099 101.079V110.06C973.099 111.821 972.571 113.317 971.514 114.55C970.458 115.607 969.049 116.135 967.288 116.135H951.968C943.691 116.135 938.056 118.336 935.062 122.738C932.069 126.965 930.572 133.128 930.572 141.228V153.115H964.646C966.407 153.115 967.816 153.731 968.873 154.964C969.929 156.02 970.458 157.429 970.458 159.19V168.171C970.458 169.932 969.929 171.429 968.873 172.661C967.816 173.718 966.407 174.246 964.646 174.246H930.572V284.393C930.572 286.154 929.956 287.651 928.723 288.884C927.667 289.94 926.258 290.469 924.497 290.469H912.082Z" fill="#2D2E2F"/>
<path d="M1017.94 340.656C1016.53 340.656 1015.3 340.127 1014.24 339.071C1013.19 338.014 1012.66 336.782 1012.66 335.373C1012.66 334.668 1012.75 333.964 1012.92 333.26C1013.1 332.555 1013.45 331.675 1013.98 330.618L1034.32 282.28L983.867 163.152C982.987 161.039 982.546 159.542 982.546 158.662C982.546 157.077 983.075 155.756 984.131 154.7C985.188 153.643 986.509 153.115 988.093 153.115H1001.04C1002.8 153.115 1004.21 153.555 1005.26 154.435C1006.32 155.316 1007.02 156.373 1007.38 157.605L1047.53 253.753L1088.73 157.605C1089.26 156.373 1089.96 155.316 1090.84 154.435C1091.9 153.555 1093.4 153.115 1095.34 153.115H1107.75C1109.33 153.115 1110.66 153.643 1111.71 154.7C1112.77 155.756 1113.3 156.989 1113.3 158.398C1113.3 159.278 1112.86 160.863 1111.98 163.152L1036.96 336.165C1036.43 337.398 1035.64 338.454 1034.58 339.335C1033.7 340.215 1032.29 340.656 1030.36 340.656H1017.94Z" fill="#2D2E2F"/>
<path d="M1128.65 290.469C1126.89 290.469 1125.4 289.94 1124.16 288.884C1123.11 287.651 1122.58 286.154 1122.58 284.393V265.375C1122.58 263.614 1123.11 262.205 1124.16 261.149C1125.4 259.916 1126.89 259.3 1128.65 259.3H1147.67C1149.43 259.3 1150.84 259.916 1151.9 261.149C1153.13 262.205 1153.75 263.614 1153.75 265.375V284.393C1153.75 286.154 1153.13 287.651 1151.9 288.884C1150.84 289.94 1149.43 290.469 1147.67 290.469H1128.65Z" fill="#2D2E2F"/>
<path d="M1244.66 348.58C1232.69 348.58 1222.83 346.995 1215.08 343.825C1207.51 340.656 1201.52 336.782 1197.12 332.203C1192.89 327.801 1189.81 323.31 1187.87 318.732C1186.11 314.329 1185.14 310.808 1184.97 308.166C1184.79 306.405 1185.32 304.908 1186.55 303.676C1187.96 302.443 1189.46 301.827 1191.04 301.827H1203.72C1205.31 301.827 1206.63 302.179 1207.68 302.883C1208.74 303.588 1209.62 305.084 1210.32 307.374C1211.38 310.015 1212.97 312.921 1215.08 316.09C1217.19 319.436 1220.45 322.254 1224.85 324.543C1229.25 327.008 1235.42 328.241 1243.34 328.241C1251.62 328.241 1258.57 327.096 1264.21 324.807C1269.84 322.694 1274.07 318.82 1276.89 313.185C1279.88 307.726 1281.38 300.154 1281.38 290.469V272.507C1277.15 277.966 1271.61 282.544 1264.74 286.242C1257.87 289.764 1249.24 291.525 1238.85 291.525C1228.99 291.525 1220.54 289.852 1213.49 286.507C1206.45 282.985 1200.64 278.318 1196.06 272.507C1191.66 266.52 1188.31 259.74 1186.02 252.168C1183.91 244.596 1182.68 236.672 1182.33 228.395C1182.15 223.465 1182.15 218.622 1182.33 213.867C1182.68 205.591 1183.91 197.667 1186.02 190.095C1188.31 182.523 1191.66 175.743 1196.06 169.756C1200.64 163.769 1206.45 159.102 1213.49 155.756C1220.54 152.234 1228.99 150.473 1238.85 150.473C1249.42 150.473 1258.13 152.498 1265 156.549C1272.05 160.423 1277.77 165.177 1282.17 170.812V159.454C1282.17 157.693 1282.7 156.196 1283.76 154.964C1284.99 153.731 1286.49 153.115 1288.25 153.115H1300.4C1302.16 153.115 1303.65 153.731 1304.89 154.964C1306.12 156.196 1306.74 157.693 1306.74 159.454V287.563C1306.74 299.361 1304.71 309.839 1300.66 318.996C1296.79 328.153 1290.27 335.373 1281.11 340.656C1272.13 345.938 1259.98 348.58 1244.66 348.58ZM1244.13 270.394C1252.94 270.394 1259.98 268.369 1265.27 264.319C1270.73 260.268 1274.69 255.162 1277.15 248.998C1279.79 242.835 1281.2 236.584 1281.38 230.244C1281.55 227.779 1281.64 224.785 1281.64 221.263C1281.64 217.565 1281.55 214.484 1281.38 212.018C1281.2 205.679 1279.79 199.428 1277.15 193.264C1274.69 187.101 1270.73 181.994 1265.27 177.944C1259.98 173.894 1252.94 171.869 1244.13 171.869C1235.33 171.869 1228.29 173.894 1223 177.944C1217.72 181.818 1213.93 187.013 1211.65 193.529C1209.36 199.868 1208.04 206.736 1207.68 214.132C1207.51 218.71 1207.51 223.377 1207.68 228.131C1208.04 235.527 1209.36 242.483 1211.65 248.998C1213.93 255.338 1217.72 260.533 1223 264.583C1228.29 268.457 1235.33 270.394 1244.13 270.394Z" fill="#2D2E2F"/>
<path d="M1394.35 293.11C1380.96 293.11 1369.78 290.557 1360.8 285.45C1351.82 280.343 1344.95 273.299 1340.2 264.319C1335.44 255.162 1332.8 244.772 1332.27 233.15C1332.1 230.156 1332.01 226.37 1332.01 221.792C1332.01 217.037 1332.1 213.251 1332.27 210.434C1332.8 198.635 1335.44 188.246 1340.2 179.265C1345.13 170.284 1352.08 163.24 1361.07 158.133C1370.05 153.027 1381.14 150.473 1394.35 150.473C1407.55 150.473 1418.65 153.027 1427.63 158.133C1436.61 163.24 1443.48 170.284 1448.23 179.265C1453.16 188.246 1455.89 198.635 1456.42 210.434C1456.6 213.251 1456.69 217.037 1456.69 221.792C1456.69 226.37 1456.6 230.156 1456.42 233.15C1455.89 244.772 1453.25 255.162 1448.5 264.319C1443.74 273.299 1436.87 280.343 1427.89 285.45C1418.91 290.557 1407.73 293.11 1394.35 293.11ZM1394.35 272.771C1405.27 272.771 1413.98 269.337 1420.5 262.47C1427.01 255.426 1430.53 245.212 1431.06 231.829C1431.24 229.188 1431.33 225.842 1431.33 221.792C1431.33 217.742 1431.24 214.396 1431.06 211.754C1430.53 198.371 1427.01 188.246 1420.5 181.378C1413.98 174.334 1405.27 170.812 1394.35 170.812C1383.43 170.812 1374.62 174.334 1367.93 181.378C1361.42 188.246 1357.98 198.371 1357.63 211.754C1357.46 214.396 1357.37 217.742 1357.37 221.792C1357.37 225.842 1357.46 229.188 1357.63 231.829C1357.98 245.212 1361.42 255.426 1367.93 262.47C1374.62 269.337 1383.43 272.771 1394.35 272.771Z" fill="#2D2E2F"/>
<path d="M1524.75 290.469C1522.1 290.469 1519.99 289.852 1518.41 288.62C1517 287.387 1515.85 285.802 1514.97 283.865L1466.11 161.303C1465.75 160.423 1465.58 159.542 1465.58 158.662C1465.58 157.077 1466.11 155.756 1467.16 154.7C1468.22 153.643 1469.54 153.115 1471.12 153.115H1483.8C1485.74 153.115 1487.24 153.643 1488.29 154.7C1489.35 155.756 1489.97 156.725 1490.14 157.605L1530.56 261.677L1570.71 157.605C1571.06 156.725 1571.67 155.756 1572.56 154.7C1573.61 153.643 1575.11 153.115 1577.05 153.115H1589.99C1591.4 153.115 1592.63 153.643 1593.69 154.7C1594.92 155.756 1595.54 157.077 1595.54 158.662C1595.54 159.542 1595.36 160.423 1595.01 161.303L1545.88 283.865C1545.17 285.802 1544.03 287.387 1542.44 288.62C1541.03 289.852 1538.92 290.469 1536.1 290.469H1524.75Z" fill="#2D2E2F"/>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="260.000000pt" height="260.000000pt" viewBox="0 0 260.000000 260.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,260.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1177 2586 c-67 -29 -117 -107 -117 -183 0 -12 -15 -24 -48 -37 -175
-69 -342 -229 -426 -406 -74 -156 -77 -183 -78 -657 l-1 -423 -123 -116 -124
-117 0 -109 0 -108 996 2 997 3 -1 105 -1 105 -123 117 -123 118 -1 310 c0
170 -3 313 -7 316 -4 4 -26 8 -50 9 -105 6 -216 59 -292 140 -152 161 -161
417 -22 583 35 42 31 48 -71 97 -42 20 -84 41 -92 45 -8 4 -18 28 -22 54 -14
100 -80 158 -182 162 -34 1 -74 -4 -89 -10z"/>
<path d="M1854 2297 c-64 -28 -95 -48 -134 -89 -65 -68 -99 -163 -94 -265 11
-271 317 -431 547 -286 163 103 215 311 122 482 -35 64 -91 114 -165 149 -77
37 -202 41 -276 9z"/>
<path d="M910 282 c0 -32 32 -116 59 -154 114 -161 427 -170 566 -16 42 47 75
119 75 165 l0 23 -350 0 c-332 0 -350 -1 -350 -18z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1 +1,19 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@@ -65,7 +65,7 @@
return $(`<div class="selection-footer${stickyClass}">
<button
class="govuk-button govuk-button--secondary selection-footer__button"
class="govuk-button govuk-button--secondary selection-footer__button usa-button usa-button--outline"
aria-expanded="${expanded ? 'true' : 'false'}"
aria-controls="${this.fieldsetId}">
${buttonContent}

View File

@@ -0,0 +1,41 @@
(function (window) {
// Set the target date (10 days before March 15th, 2024)
const targetDate = new Date("April 16, 2024 00:00:00").getTime();
// Set a const for the container to write a conditional statement and only run if it exists
const countdownContainer = document.getElementById("countdown-container");
// Function to update the countdown display
function updateCountdown() {
if (countdownContainer) {
const now = new Date().getTime();
const difference = targetDate - now;
// Time calculations for days only
const days = Math.floor(difference / (1000 * 60 * 60 * 24));
// Visibility logic
if (days < 0 || days > 10) {
// Hide if more than 10 days away OR if already past the date
countdownContainer.style.display = "none";
} else {
// Show if 10 days or less remaining
countdownContainer.style.display = "block";
document.getElementById("countdown").innerHTML = days + " days ";
}
}
}
// Expose the updateCountdown function to the outside world
window.updateCountdown = updateCountdown;
// Initial display update
updateCountdown();
// Update the countdown every second (inside the IIFE)
setInterval(updateCountdown, 1000);
})(window);

View File

@@ -48,13 +48,13 @@
}
}
.sms-message-sender {
margin: units(1) 0 0;
.sms-message-sender, .sms-message-file-name, .sms-message-scheduler, .sms-message-template, .sms-message-sender {
margin:0.25rem 0 0;
}
.sms-message-recipient {
color: color('gray-cool-90');
margin: 0 0 units(1);
margin: units(1) 0 units(1);
}
.sms-message-status {
@@ -62,6 +62,14 @@
margin: -20px units(1) 20px units(1);
}
h2.sms-message-header {
margin-bottom: 0.5rem;
}
h2.recipient-list {
margin-bottom: 0.5rem;
}
.sms-message-status-outbound {
text-align: right;
}
@@ -131,7 +139,7 @@
&-label,
&-button-label {
font-weight: bold;
font-size: 19px;
font-size: 19px;
display: block;
margin: 0 0 10px 0;
}

View File

@@ -22,27 +22,46 @@ i.e.
@use "uswds-core" as *;
iframe:focus, [href]:focus, [tabindex]:focus, [contentEditable=true]:focus {
outline: units(1px) dotted color('blue-40v');
outline: units(1px) auto color('blue-40v');
outline-offset: 0.3rem;
}
.usa-header--extended {
.usa-logo {
font-family: family("sans");
margin: units(4) 0;
@include at-media-max('mobile-lg') {
margin: units(3) 0;
@include at-media-max('desktop') {
margin: units(4) 0 units(4) units(2);
}
img {
@include at-media($theme-header-min-width) {
width: 80px;
height: 70px;
a {
display: flex;
img {
height: 35px;
@include at-media('desktop') {
height: 60px;
}
}
}
}
.usa-nav__secondary {
.usa-nav__link {
padding: 0;
&.usa-current {
text-decoration: underline;
}
padding: 0;
&.usa-current {
text-decoration: underline;
}
}
@include at-media-max('desktop') {
padding: 0 units(2);
ul li {
padding-bottom: units(1);
}
}
}
.usa-nav-container {
max-width: 100%;
padding: 0;
}
}
@@ -52,18 +71,23 @@ i.e.
.usa-nav__primary {
&> .usa-nav__primary-item > a {
font-size: size("body", 4);
font-size: size("body", 5);
font-weight: 400;
cursor: pointer;
}
// &> .usa-nav__primary-item:last-child {
// margin-left: auto;
// @include u-margin-right(-4);
// }
}
h1 {
font-weight: bold !important;
}
.usa-section--dark h1 {
color: color('blue-30v');
@include at-media-max('desktop') {
font-size: size("body", 12);
}
}
p,
.list li {
font-family: family("sans");
@@ -124,6 +148,7 @@ td.table-empty-message {
.button-flex-header {
flex-direction: column;
align-items: flex-start;
margin-bottom: units(2);
@include at-media(desktop) {
flex-direction: row;
display: flex;
@@ -139,27 +164,37 @@ td.table-empty-message {
}
.user-list {
display: inline-flex;
display: flex;
flex-wrap: wrap;
gap: units(2);
.user-list-item {
@include at-media(desktop) {
flex: 1 1 calc(50% - units(2));
}
flex: 1 1 calc(100% - units(2));
border: 1px solid color('gray-cool-10');
padding: units(2);
.tick-cross-list-permissions {
margin: units(1) 0;
padding-left: units(2);
}
.hint {
display: block;
font-size: size("body", "sm");
font-weight: normal;
}
justify-content: space-between;
padding: 1rem;
}
.user-list-item {
@include at-media(desktop) {
width: calc(50% - units(1));
margin-bottom: 1rem;
box-sizing: border-box;
}
}
.user-list-item-heading .live-search-relevant {
display: block;
word-wrap: break-word;
}
border: 1px solid color('gray-cool-10');
padding: units(2);
.tick-cross-list-permissions {
margin: units(1) 0;
padding-left: units(2);
}
.hint {
display: block;
font-size: size("body", "sm");
font-weight: normal;
}
}
.template-list-item-without-ancestors .template-list-folder:active,
.template-list-item-without-ancestors .template-list-folder:active::before,
@@ -284,27 +319,15 @@ td.table-empty-message {
.dashboard {
.big-number-with-status {
a {
background: color("blue-60v");
padding: units(2);
margin-bottom: units(1);
text-decoration: none;
&:hover{
background: color("blue-warm-70v");
}
}
span {
color: white;
}
.big-number-smaller {
display: flex;
flex-direction: column;
.big-number-number {
font-size: units(5);
line-height: units(6);
line-height: units(5);
}
.big-number-label {
font-size: units(3);
font-size: units(2.5);
}
}
.big-number-status {
@@ -341,6 +364,9 @@ td.table-empty-message {
background-image: url(../img/material-icons/description.svg);
}
}
.table-wrapper {
overflow-x: scroll;
}
}
.dashboard-table {
@@ -352,6 +378,7 @@ td.table-empty-message {
}
.file-list-hint {
margin: 0;
word-break: break-word;
}
.table-field, .table-field-right-aligned {
width: 50%;
@@ -375,6 +402,36 @@ td.table-empty-message {
}
}
.job-table {
width: 100%;
border-collapse: collapse;
td.file-name {
width: 25%;
overflow-wrap: anywhere;
}
td.template {
width: 20%;
}
td.time-sent {
width: 20%;
}
td.sender {
width: 15%;
}
td.count-of-recipients {
width: 5%;
}
td.report {
width: 5%;
}
th {
padding: 0.5rem 1rem
}
td {
padding: 0.5rem 1rem
}
}
#template-list {
max-height: 500px;
overflow-y: auto;
@@ -520,3 +577,15 @@ details form {
.edit-textbox-error-mt {
margin-top: 1.5rem;
}
// Login page
#countdown-container {
display: none; // Hide the countdown timer
}
.placeholder, .placeholder-conditional {
background-color: #face00;
border: 1px solid #face00;
border-radius: 7px;
}

View File

@@ -9,5 +9,9 @@ in the form $setting: value,
@use "uswds-core" with (
$theme-font-type-sans: "public-sans",
$theme-show-notifications: false
$theme-show-notifications: false,
$theme-banner-max-width: "desktop-lg",
$theme-grid-container-max-width: "desktop-lg",
$theme-footer-max-width: "desktop-lg",
$theme-header-max-width: "desktop-lg"
);

View File

@@ -36,11 +36,7 @@ class Config(object):
NR_BROWSER_KEY = getenv("NR_BROWSER_KEY")
settings = newrelic.agent.global_settings()
NR_MONITOR_ON = settings and settings.monitor_mode
TEMPLATE_PREVIEW_API_HOST = getenv(
"TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999"
)
TEMPLATE_PREVIEW_API_KEY = getenv("TEMPLATE_PREVIEW_API_KEY", "my-secret-key")
COMMIT_HASH = getenv("COMMIT_HASH", "--------")[0:7]
GOVERNMENT_EMAIL_DOMAIN_NAMES = ["gov"]
@@ -81,8 +77,7 @@ class Config(object):
"IBAN": "GB33BUKB20201555555555",
"swift": "ABCDEF12",
"notify_billing_email_addresses": [
"generic@digital.cabinet-office.gov.uk",
"first.last@digital.cabinet-office.gov.uk",
"tts-benefits-studio@gsa.gov",
],
}
@@ -152,6 +147,34 @@ class Staging(Production):
HEADER_COLOUR = "#00ff00" # $green
class E2ETest(Staging):
"""
An environment config that is intended to operate as if it were in the
staging environment but with the configuration of the development and test
environments so the E2E tests work.
"""
# Borrowed from development environment
DEBUG = True
SESSION_COOKIE_SECURE = False
SESSION_PROTECTION = None
HTTP_PROTOCOL = "http"
ASSET_DOMAIN = ""
ASSET_PATH = "/static/"
# Borrowed from test environment
TESTING = True
WTF_CSRF_ENABLED = False
# buckets - mirror staging
CSV_UPLOAD_BUCKET = cloud_config.s3_credentials(
"notify-api-csv-upload-bucket-staging"
)
LOGO_UPLOAD_BUCKET = cloud_config.s3_credentials(
"notify-admin-logo-upload-bucket-staging"
)
class Demo(Staging):
HEADER_COLOUR = "#6F72AF" # $mauve
@@ -173,6 +196,7 @@ class Scanning(Production):
configs = {
"development": Development,
"test": Test,
"e2etest": E2ETest,
"scanning": Scanning,
"staging": Staging,
"demo": Demo,

View File

@@ -1,43 +1,21 @@
# Get started
1. ## Check if Notify.gov is right for you
<p>Read about our <a class="usa-link" href="{{ url_for('main.features') }}">features</a>, <a class="usa-link" href="{{ url_for('.pricing') }}">pricing</a> and <a class="usa-link" href="{{ url_for('main.roadmap') }}">roadmap</a>.</p>
1. ## Everyone starts in [Trial Mode](/using-notify/trial-mode)
Explore Notify, add team members, and practice [sending messages to teammates](/using-notify/trial-mode).
2. ## Personalize content
Learn how to [personalize messages](/using-notify/guidance) to increase response.
2. ## Create an account
{% if not current_user.is_authenticated %}
<p><a class="usa-link" href="{{ url_for('.register') }}">Create an account</a> for free and add your first Notify service. When you add a new service it will start in <a class="usa-link" href="{{ url_for('main.trial_mode_new') }}">trial mode</a>.</p>
{% else %}
<p>Create an account for free and add your first Notify service. When you add a new service, it will start in <a class="usa-link" href="{{ url_for('main.trial_mode_new') }}">trial mode</a>.</p>
{% endif %}
3. ## Write some messages
{% if True %}
<p>Add message templates with examples of the content you plan to send. You can use our <a class="usa-link" href="{{ url_for('main.guidance_index') }}">guidance</a> to help you.</p>
{% endif %}
4. ## Set up your service
{% if not current_user.is_authenticated or not current_service %}
<p>Review your settings to add message branding and sender information.</p>
<p>Add team members and check their permissions.</p>
{% else %}
<p>Review your <a class="usa-link" href="{{ url_for('.service_settings', service_id=current_service.id) }}">settings</a> to add message branding and sender information.</p>
<p>Add <a class="usa-link" href="{{ url_for('.manage_users', service_id=current_service.id) }}">team members</a> and check their permissions.</p>
{% endif %}
3. ## Check delivery status
[Analyze the delivery](/using-notify/delivery-status) of your messages and download reports
4. ## View messaging limits
Learn about message _parts_ and [how limits are calculated](/using-notify/pricing).
5. ## Start sending messages
{% if not current_user.is_authenticated or not current_service %}
<p>When youre ready to send messages to people outside your team, go to the <b class="bold">Settings</b> page and select <b class="bold">Request to go live</b>. Well approve your request within one working day.</p>
{% else %}
<p>You should <a class="usa-link" href="{{ url_for('.support') }}">request to go live</a> when youre ready to send messages to people outside your team. Well approve your request within one working day.</p>
{% endif %}
To remove the restrictions of Trial Mode and begin sending messages to clients complete the [Live Campaign Form](https://airtable.com/appe4n7jYOALPLcyU/shrIPWnLTw9U1fclL).
Well respond within one business day.
<!-- <li class="get-started-list__item">
<h2 class="usa-process-list__heading line-height-sans-1">Set up an API integration (optional)</h2>
<p>You can use the Notify API to send messages automatically.</p>
<p>Our <a class="usa-link" href="{{ url_for('main.documentation') }}">documentation</a> explains how to integrate the API with a web application or back office system.</p>
</li> -->
<!-- <p>Check <a class="usa-link" href="{{ url_for('main.how_to_pay') }}">how to pay</a> if youre planning to exceed the <a class="usa-link" href="{{ url_for('.pricing', _anchor='text-messages') }}">free text message allowance</a>.</p> -->
### Questions?
[Contact the Notify team](/support)

View File

@@ -22,7 +22,7 @@ from notifications_utils.recipients import InvalidPhoneError, validate_phone_num
from notifications_utils.take import Take
from app.utils.csv import get_user_preferred_timezone
from app.utils.time import parse_naive_dt
from app.utils.time import parse_dt, parse_naive_dt
def apply_html_class(tags, html_file):
@@ -87,15 +87,22 @@ def format_time(date):
def format_datetime_normal(date):
# example: February 20, 2024 at 07:00 PM US/Eastern, used for datetimes that's not within tables
return "{} at {} {}".format(
format_date_normal(date), format_time_24h(date), get_user_preferred_timezone()
format_date_normal(date), format_time_12h(date), get_user_preferred_timezone()
)
def format_datetime_short(date):
return "{} at {} {}".format(
format_date_short(date), format_time_24h(date), get_user_preferred_timezone()
)
def format_datetime_table(date):
# example: 03-18-2024 at 04:53 PM, intended for datetimes in tables
return "{} at {}".format(format_date_numeric(date), format_time_12h(date))
def format_time_12h(date):
date = parse_dt(date)
preferred_tz = pytz.timezone(get_user_preferred_timezone())
return date.astimezone(preferred_tz).strftime("%I:%M %p")
def format_datetime_relative(date):
@@ -115,7 +122,7 @@ def format_date_numeric(date):
preferred_tz = pytz.timezone(get_user_preferred_timezone())
return (
date.replace(tzinfo=timezone.utc).astimezone(preferred_tz).strftime("%Y-%m-%d")
date.replace(tzinfo=timezone.utc).astimezone(preferred_tz).strftime("%m-%d-%Y")
)
@@ -164,7 +171,7 @@ def format_date(date):
def format_date_normal(date):
date = parse_naive_dt(date)
return date.strftime("%d %B %Y").lstrip("0")
return date.strftime("%B %d, %Y").lstrip("0")
def format_date_short(date):
@@ -448,6 +455,12 @@ def message_count_noun(count, template_type):
else:
return "text messages"
if template_type == "parts":
if count == 1:
return "text message part"
else:
return "text message parts"
elif template_type == "email":
if count == 1:
return "email"

View File

@@ -70,7 +70,7 @@ from app.utils.user_permissions import all_ui_permissions, permission_options
def get_time_value_and_label(future_time):
preferred_tz = pytz.timezone(get_user_preferred_timezone())
return (
future_time.astimezone(preferred_tz).replace(tzinfo=None).isoformat(),
future_time.astimezone(preferred_tz).isoformat(),
"{} at {} {}".format(
get_human_day(future_time.astimezone(preferred_tz)),
get_human_time(future_time.astimezone(preferred_tz)),
@@ -605,6 +605,15 @@ class RegisterUserForm(StripWhitespaceForm):
auth_type = HiddenField("auth_type", default="sms_auth")
class SetupUserProfileForm(StripWhitespaceForm):
name = GovukTextInputField(
"Full name", validators=[DataRequired(message="Cannot be empty")]
)
mobile_number = international_phone_number()
# TODO This should be replaced with a select widget when one is available.
preferred_timezone = HiddenField("preferred_timezone", default="US/Eastern")
class RegisterUserFromInviteForm(RegisterUserForm):
def __init__(self, invited_user):
super().__init__(
@@ -1226,7 +1235,11 @@ class CsvUploadForm(StripWhitespaceForm):
validators=[
DataRequired(message="Please pick a file"),
CsvFileValidator(),
FileSize(max_size=10e6, message="File must be smaller than 10Mb"), # 10Mb
FileSize(
max_size=10e6,
message="File must be smaller than 10Mb. If you are trying to upload an Excel file, \
please export the contents in the CSV format and then try again.",
), # 10Mb
],
)
@@ -1253,7 +1266,6 @@ class ChangePreferredTimezoneForm(StripWhitespaceForm):
new_preferred_timezone = GovukRadiosField(
"What timezone would you like to use?",
default="US/Eastern",
)
@@ -1782,12 +1794,16 @@ class TemplateAndFoldersSelectionForm(Form):
None,
[
# ('email', 'Email') if 'email' in available_template_types else None,
("sms", "Start with a blank template")
if "sms" in available_template_types
else None,
("copy-existing", "Copy an existing template")
if allow_adding_copy_of_template
else None,
(
("sms", "Start with a blank template")
if "sms" in available_template_types
else None
),
(
("copy-existing", "Copy an existing template")
if allow_adding_copy_of_template
else None
),
],
)
)

View File

@@ -168,12 +168,14 @@ def api_callbacks(service_id):
return render_template(
"views/api/callbacks.html",
received_text_messages_callback=received_text_messages_callback["url"]
if received_text_messages_callback
else None,
delivery_status_callback=delivery_status_callback["url"]
if delivery_status_callback
else None,
received_text_messages_callback=(
received_text_messages_callback["url"]
if received_text_messages_callback
else None
),
delivery_status_callback=(
delivery_status_callback["url"] if delivery_status_callback else None
),
)
@@ -262,9 +264,11 @@ def received_text_messages_callback(service_id):
received_text_messages_callback = get_received_text_messages_callback()
form = CallbackForm(
url=received_text_messages_callback.get("url")
if received_text_messages_callback
else "",
url=(
received_text_messages_callback.get("url")
if received_text_messages_callback
else ""
),
bearer_token=dummy_bearer_token if received_text_messages_callback else "",
)

View File

@@ -1,4 +1,5 @@
import calendar
from collections import defaultdict
from datetime import datetime
from functools import partial
from itertools import groupby
@@ -47,54 +48,41 @@ def service_dashboard(service_id):
if not current_user.has_permissions("view_activity"):
return redirect(url_for("main.choose_template", service_id=service_id))
download_availability = []
notifications = notification_api_client.get_notifications_for_service(
service_id=service_id,
job_response = job_api_client.get_jobs(service_id)["data"]
notifications_response = notification_api_client.get_notifications_for_service(
service_id
)["notifications"]
notificaton_job_ids = [
notification["job"]["id"]
for notification in notifications
if "job" in notification
]
jobs = []
for notificaton_job_id in notificaton_job_ids:
job_data = job_api_client.get_job(service_id, notificaton_job_id)["data"]
if job_data:
jobs.append(job_data)
service_data_retention_days = 7
download_availability = []
for job in jobs:
message_type = job.get("template_type")
if message_type is not None:
service_data_retention_days = current_service.get_days_of_retention(
message_type
)
time_left = get_time_left(job["created_at"])
download_link = (
url_for(
".view_job_csv",
service_id=current_service.id,
job_id=job["id"],
aggregate_notifications_by_job = defaultdict(list)
for notification in notifications_response:
job_id = notification.get("job", {}).get("id", None)
if job_id:
aggregate_notifications_by_job[job_id].append(notification)
job_and_notifications = [
{
"job_id": job["id"],
"time_left": get_time_left(job["created_at"]),
"download_link": url_for(
".view_job_csv", service_id=current_service.id, job_id=job["id"]
),
)
download_availability.append(
{
"job_id": job["id"],
"time_left": time_left,
"download_link": download_link,
}
)
"view_job_link": url_for(
".view_job", service_id=current_service.id, job_id=job["id"]
),
"created_at": job["created_at"],
"notification_count": job["notification_count"],
"created_by": job["created_by"],
"notifications": aggregate_notifications_by_job.get(job["id"], []),
}
for job in job_response
if aggregate_notifications_by_job.get(job["id"], [])
]
return render_template(
"views/dashboard/dashboard.html",
updates_url=url_for(".service_dashboard_updates", service_id=service_id),
partials=get_dashboard_partials(service_id),
notifications=notifications,
download_availability=download_availability,
job_and_notifications=job_and_notifications,
service_data_retention_days=service_data_retention_days,
)

View File

@@ -1,3 +1,5 @@
import os
from flask import abort, redirect, render_template, request, url_for
from flask_login import current_user
@@ -8,6 +10,8 @@ from app.main.views.pricing import CURRENT_SMS_RATE
from app.main.views.sub_navigation_dictionaries import features_nav, using_notify_nav
from app.utils.user import user_is_logged_in
login_dot_gov_url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
@main.route("/")
def index():
@@ -18,6 +22,7 @@ def index():
"views/signedout.html",
sms_rate=CURRENT_SMS_RATE,
counts=status_api_client.get_count_of_live_services_and_organizations(),
login_dot_gov_url=login_dot_gov_url,
)
@@ -102,15 +107,6 @@ def security():
return render_template("views/security.html", navigation_links=features_nav())
@main.route("/features/terms", endpoint="terms")
@user_is_logged_in
def terms():
return render_template(
"views/terms-of-use.html",
navigation_links=features_nav(),
)
@main.route("/features/using_notify")
@user_is_logged_in
def using_notify():
@@ -214,7 +210,6 @@ def send_files_by_email():
@main.route("/roadmap", endpoint="old_roadmap")
@main.route("/terms", endpoint="old_terms")
@main.route("/information-security", endpoint="information_security")
@main.route("/using_notify", endpoint="old_using_notify")
@main.route("/information-risk-management", endpoint="information_risk_management")
@@ -222,7 +217,6 @@ def send_files_by_email():
def old_page_redirects():
redirects = {
"main.old_roadmap": "main.roadmap",
"main.old_terms": "main.terms",
"main.information_security": "main.using_notify",
"main.old_using_notify": "main.using_notify",
"main.information_risk_management": "main.security",

View File

@@ -10,6 +10,7 @@ from flask import (
redirect,
render_template,
request,
session,
stream_with_context,
url_for,
)
@@ -18,7 +19,7 @@ from notifications_utils.template import EmailPreviewTemplate, SMSBodyPreviewTem
from app import (
current_service,
format_datetime_short,
format_datetime_table,
notification_api_client,
service_api_client,
)
@@ -93,7 +94,7 @@ def view_job_csv(service_id, job_id):
mimetype="text/csv",
headers={
"Content-Disposition": 'inline; filename="{} - {}.csv"'.format(
job.template["name"], format_datetime_short(job.created_at)
job.template["name"], format_datetime_table(job.created_at)
)
},
)
@@ -276,12 +277,16 @@ def get_status_filters(service, message_type, statistics):
}
else:
stats = statistics[message_type]
stats["sending"] = stats["requested"] - stats["delivered"] - stats["failed"]
if stats.get("failure") is not None:
stats["failed"] = stats["failure"]
stats["pending"] = stats["requested"] - stats["delivered"] - stats["failed"]
filters = [
# key, label, option
("requested", "total", "sending,delivered,failed"),
("sending", "pending", "pending"),
("pending", "pending", "pending"),
("delivered", "delivered", "delivered"),
("failed", "failed", "failed"),
]
@@ -296,7 +301,7 @@ def get_status_filters(service, message_type, statistics):
message_type=message_type,
status=option,
),
stats[key],
stats.get(key),
)
for key, label, option in filters
]
@@ -369,6 +374,13 @@ def get_job_partials(job):
job.template_type
)
if request.referrer is not None:
session["arrived_from_preview_page"] = "check" in request.referrer
else:
session["arrived_from_preview_page"] = False
arrived_from_preview_page_url = session.get("arrived_from_preview_page", False)
return {
"counts": counts,
"notifications": render_template(
@@ -392,6 +404,7 @@ def get_job_partials(job):
"status": render_template(
"partials/jobs/status.html",
job=job,
arrived_from_preview_page_url=arrived_from_preview_page_url,
),
}

View File

@@ -122,16 +122,18 @@ def edit_user_permissions(service_id, user_id):
form = form_class.from_user(
user,
service_id,
folder_permissions=None
if user.platform_admin
else [
f["id"]
for f in current_service.all_template_folders
if user.has_template_folder_permission(f)
],
all_template_folders=None
if user.platform_admin
else current_service.all_template_folders,
folder_permissions=(
None
if user.platform_admin
else [
f["id"]
for f in current_service.all_template_folders
if user.has_template_folder_permission(f)
]
),
all_template_folders=(
None if user.platform_admin else current_service.all_template_folders
),
)
if form.validate_on_submit():

View File

@@ -11,12 +11,7 @@ from flask import (
url_for,
)
from app import (
current_service,
format_date_numeric,
job_api_client,
notification_api_client,
)
from app import current_service, job_api_client, notification_api_client
from app.main import main
from app.notify_client.api_key_api_client import KEY_TYPE_TEST
from app.utils import (
@@ -26,7 +21,7 @@ from app.utils import (
parse_filter_args,
set_status_filters,
)
from app.utils.csv import generate_notifications_csv
from app.utils.csv import generate_notifications_csv, get_user_preferred_timezone
from app.utils.templates import get_template
from app.utils.user import user_has_permissions
@@ -95,7 +90,7 @@ def view_notification(service_id, notification_id, error_message=None):
partials=get_single_notification_partials(notification),
created_by=notification.get("created_by"),
created_at=notification["created_at"],
updated_at=notification["updated_at"],
updated_at=notification["sent_at"],
help=get_help_argument(),
notification_id=notification["id"],
can_receive_inbound=(current_service.has_permission("inbound_sms")),
@@ -146,6 +141,9 @@ def download_notifications_csv(service_id):
service_data_retention_days = current_service.get_days_of_retention(
filter_args.get("message_type")[0]
)
file_time = datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
file_time = f"{file_time} {get_user_preferred_timezone()}"
return Response(
stream_with_context(
generate_notifications_csv(
@@ -162,7 +160,7 @@ def download_notifications_csv(service_id):
mimetype="text/csv",
headers={
"Content-Disposition": 'inline; filename="{} - {} - {} report.csv"'.format(
format_date_numeric(datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ")),
file_time,
filter_args["message_type"][0],
current_service.name,
)

View File

@@ -34,8 +34,8 @@ def performance():
stats["average_percentage_under_10_seconds"] = mean(
[row["percentage_under_10_seconds"] for row in stats["processing_time"]] or [0]
)
stats[
"count_of_live_services_and_organizations"
] = status_api_client.get_count_of_live_services_and_organizations()
stats["count_of_live_services_and_organizations"] = (
status_api_client.get_count_of_live_services_and_organizations()
)
return render_template("views/performance.html", **stats)

View File

@@ -1,14 +1,26 @@
import uuid
from datetime import datetime, timedelta
from flask import abort, redirect, render_template, session, url_for
from flask import (
abort,
current_app,
redirect,
render_template,
request,
session,
url_for,
)
from flask_login import current_user
from app import user_api_client
from app.main import main
from app.main.forms import (
RegisterUserForm,
RegisterUserFromInviteForm,
RegisterUserFromOrgInviteForm,
SetupUserProfileForm,
)
from app.main.views import sign_in
from app.main.views.verify import activate_user
from app.models.user import InvitedOrgUser, InvitedUser, User
from app.utils import hide_from_search_engines
@@ -120,4 +132,47 @@ def _do_registration(form, send_sms=True, send_email=True, organization_id=None)
def registration_continue():
if not session.get("user_details"):
return redirect(url_for(".show_accounts_or_dashboard"))
return render_template("views/registration-continue.html")
else:
raise Exception("Unexpected routing in registration_continue")
@main.route("/set-up-your-profile", methods=["GET", "POST"])
@hide_from_search_engines
def set_up_your_profile():
form = SetupUserProfileForm()
if form.validate_on_submit():
# start login.gov
code = request.args.get("code")
state = request.args.get("state")
login_gov_error = request.args.get("error")
if code and state:
access_token = sign_in._get_access_token(code, state)
user_email, user_uuid = sign_in._get_user_email_and_uuid(access_token)
redirect_url = request.args.get("next")
elif login_gov_error:
current_app.logger.error(f"login.gov error: {login_gov_error}")
raise Exception(f"Could not login with login.gov {login_gov_error}")
# end login.gov
# create the user
# TODO we have to provide something for password until that column goes away
# TODO ideally we would set the user's preferred timezone here as well
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
if user is None:
user = User.register(
name=form.name.data,
email_address=user_email,
mobile_number=form.mobile_number.data,
password=str(uuid.uuid4()),
auth_type="sms_auth",
)
# activate the user
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
activate_user(user["id"])
return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url))
return render_template("views/set-up-your-profile.html", form=form)

View File

@@ -1,4 +1,3 @@
import itertools
import time
import uuid
from string import ascii_uppercase
@@ -6,6 +5,7 @@ from zipfile import BadZipFile
from flask import abort, flash, redirect, render_template, request, session, url_for
from flask_login import current_user
from markupsafe import Markup
from notifications_python_client.errors import HTTPError
from notifications_utils import SMS_CHAR_COUNT_LIMIT
from notifications_utils.insensitive_dict import InsensitiveDict
@@ -52,12 +52,14 @@ def get_example_csv_fields(column_headers, use_example_as_example, submitted_fie
def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False):
return {
"email": ["test@example.com"]
if use_example_as_example
else [current_user.email_address],
"sms": ["12223334444"]
if use_example_as_example
else [current_user.mobile_number],
"email": (
["test@example.com"]
if use_example_as_example
else [current_user.email_address]
),
"sms": (
["12223334444"] if use_example_as_example else [current_user.mobile_number]
),
}[template.template_type] + get_example_csv_fields(
(
placeholder
@@ -149,8 +151,11 @@ def send_messages(service_id, template_id):
# just show the first error, as we don't expect the form to have more
# than one, since it only has one field
first_field_errors = list(form.errors.values())[0]
flash(first_field_errors[0])
error_message = '<span class="usa-error-message">'
error_message = f"{error_message}{first_field_errors[0]}"
error_message = f"{error_message}</span>"
error_message = Markup(error_message)
flash(error_message)
column_headings = get_spreadsheet_column_headings_from_template(template)
return render_template(
@@ -465,7 +470,7 @@ def send_one_off_step(service_id, template_id, step_index):
)
def _check_messages(service_id, template_id, upload_id, preview_row):
def _check_messages(service_id, template_id, upload_id, preview_row, **kwargs):
try:
# The happy path is that the job doesnt already exist, so the
# API will return a 404 and the client will raise HTTPError.
@@ -502,21 +507,34 @@ def _check_messages(service_id, template_id, upload_id, preview_row):
template = get_template(
db_template,
current_service,
show_recipient=True,
show_recipient=False,
email_reply_to=email_reply_to,
sms_sender=sms_sender,
**kwargs,
)
allow_list = []
if current_service.trial_mode:
# Adding the simulated numbers to allow list
# so they can be sent in trial mode
for user in Users(service_id):
allow_list.extend([user.name, user.mobile_number, user.email_address])
# Failed sms number
allow_list.extend(
["simulated user (fail)", "+14254147167", "simulated@simulated.gov"]
)
# Success sms number
allow_list.extend(
["simulated user (success)", "+14254147755", "simulatedtwo@simulated.gov"]
)
else:
allow_list = None
recipients = RecipientCSV(
contents,
template=template,
max_initial_rows_shown=50,
max_errors_shown=50,
guestlist=itertools.chain.from_iterable(
[user.name, user.mobile_number, user.email_address]
for user in Users(service_id)
)
if current_service.trial_mode
else None,
guestlist=allow_list,
remaining_messages=remaining_messages,
allow_international_sms=current_service.has_permission("international_sms"),
)
@@ -526,11 +544,20 @@ def _check_messages(service_id, template_id, upload_id, preview_row):
back_link = url_for(
"main.send_one_off", service_id=service_id, template_id=template.id
)
back_link_from_preview = url_for(
"main.send_one_off", service_id=service_id, template_id=template.id
)
choose_time_form = None
else:
back_link = url_for(
"main.send_messages", service_id=service_id, template_id=template.id
)
back_link_from_preview = url_for(
"main.check_messages",
service_id=service_id,
template_id=template.id,
upload_id=upload_id,
)
choose_time_form = ChooseTimeForm()
if preview_row < 2:
@@ -558,11 +585,13 @@ def _check_messages(service_id, template_id, upload_id, preview_row):
remaining_messages=remaining_messages,
choose_time_form=choose_time_form,
back_link=back_link,
back_link_from_preview=back_link_from_preview,
first_recipient_column=recipients.recipient_column_headers[0],
preview_row=preview_row,
sent_previously=job_api_client.has_sent_previously(
service_id, template.id, db_template["version"], original_file_name
),
template_id=template_id,
)
@@ -610,13 +639,34 @@ def check_messages(service_id, template_id, upload_id, row_index=2):
return render_template("views/check/ok.html", **data)
@main.route(
"/services/<uuid:service_id>/<uuid:template_id>/check/<uuid:upload_id>/preview",
methods=["POST"],
)
@main.route(
"/services/<uuid:service_id>/<uuid:template_id>/check/<uuid:upload_id>/preview/row-<int:row_index>",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def preview_job(service_id, template_id, upload_id, row_index=2):
session["scheduled_for"] = request.form.get("scheduled_for", "")
data = _check_messages(service_id, template_id, upload_id, row_index, force_hide_sender=True)
return render_template(
"views/check/preview.html",
scheduled_for=session["scheduled_for"],
**data,
)
@main.route("/services/<uuid:service_id>/start-job/<uuid:upload_id>", methods=["POST"])
@user_has_permissions("send_messages", restrict_admin_usage=True)
def start_job(service_id, upload_id):
scheduled_for = session.pop("scheduled_for", None)
job_api_client.create_job(
upload_id,
service_id,
scheduled_for=request.form.get("scheduled_for", ""),
scheduled_for=scheduled_for,
)
session.pop("sender_id", None)
@@ -675,7 +725,20 @@ def get_send_test_page_title(template_type, entering_recipient, name=None):
return "Personalize this message"
def get_back_link(service_id, template, step_index, placeholders=None):
def get_back_link(
service_id,
template,
step_index,
placeholders=None,
preview=False,
):
if preview:
return url_for(
"main.check_notification",
service_id=service_id,
template_id=template.id,
)
if step_index == 0:
if should_skip_template_page(template._template):
return url_for(
@@ -754,11 +817,11 @@ def send_one_off_to_myself(service_id, template_id):
def check_notification(service_id, template_id):
return render_template(
"views/notifications/check.html",
**_check_notification(service_id, template_id),
**_check_notification(service_id, template_id, show_recipient=True),
)
def _check_notification(service_id, template_id, exception=None):
def _check_notification(service_id, template_id, exception=None, **kwargs):
db_template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
)
@@ -771,15 +834,20 @@ def _check_notification(service_id, template_id, exception=None):
template = get_template(
db_template,
current_service,
show_recipient=True,
email_reply_to=email_reply_to,
sms_sender=sms_sender,
**kwargs,
)
placeholders = fields_to_fill_in(template)
back_link = get_back_link(service_id, template, len(placeholders), placeholders)
back_link_from_preview = get_back_link(
service_id, template, len(placeholders), placeholders, preview=True
)
choose_time_form = ChooseTimeForm()
if (not session.get("recipient")) or not all_placeholders_in_session(
template.placeholders
):
@@ -791,6 +859,8 @@ def _check_notification(service_id, template_id, exception=None):
return dict(
template=template,
back_link=back_link,
back_link_from_preview=back_link_from_preview,
choose_time_form=choose_time_form,
**(get_template_error_dict(exception) if exception else {}),
)
@@ -821,12 +891,39 @@ def get_template_error_dict(exception):
}
@main.route(
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check/preview",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def preview_notification(service_id, template_id):
recipient = get_recipient()
if not recipient:
return redirect(
url_for(
".send_one_off",
service_id=service_id,
template_id=template_id,
)
)
session["scheduled_for"] = request.form.get("scheduled_for", "")
return render_template(
"views/notifications/preview.html",
**_check_notification(service_id, template_id, show_recipient=False, force_hide_sender=True),
scheduled_for=session["scheduled_for"],
recipient=recipient,
)
@main.route(
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
recipient = get_recipient()
if not recipient:
return redirect(
@@ -861,7 +958,7 @@ def send_notification(service_id, template_id):
job_api_client.create_job(
upload_id,
service_id,
scheduled_for="",
scheduled_for=scheduled_for,
template_id=template_id,
original_file_name=filename,
notification_count=1,
@@ -877,14 +974,20 @@ def send_notification(service_id, template_id):
service_id, job_id=upload_id, include_one_off=True
)
attempts = 0
while notifications["total"] == 0 and attempts < 5:
# The response can come back in different forms of incompleteness
while (
notifications["total"] == 0
and notifications["notifications"] == []
and attempts < 50
):
notifications = notification_api_client.get_notifications_for_service(
service_id, job_id=upload_id, include_one_off=True
)
time.sleep(0.1)
attempts = attempts + 1
if notifications["total"] == 0 and attempts == 5:
if notifications["total"] == 0 and attempts == 50:
# This shows the job we auto-generated for the user
return redirect(
url_for(
@@ -896,8 +999,9 @@ def send_notification(service_id, template_id):
return redirect(
url_for(
".view_notification",
".view_job",
service_id=service_id,
job_id=upload_id,
from_job=upload_id,
notification_id=notifications["notifications"][0]["id"],
# used to show the final step of the tour (help=3) or not show

View File

@@ -477,9 +477,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id):
current_service.id,
reply_to_email_id=reply_to_email_id,
email_address=form.email_address.data,
is_default=True
if reply_to_email_address["is_default"]
else form.is_default.data,
is_default=(
True
if reply_to_email_address["is_default"]
else form.is_default.data
),
)
return redirect(url_for(".service_email_reply_to", service_id=service_id))
try:
@@ -499,9 +501,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id):
".service_verify_reply_to_address",
service_id=service_id,
notification_id=notification_id,
is_default=True
if reply_to_email_address["is_default"]
else form.is_default.data,
is_default=(
True
if reply_to_email_address["is_default"]
else form.is_default.data
),
replace=reply_to_email_id,
)
)
@@ -702,9 +706,11 @@ def service_edit_sms_sender(service_id, sms_sender_id):
service_api_client.update_sms_sender(
current_service.id,
sms_sender_id=sms_sender_id,
sms_sender=sms_sender["sms_sender"]
if is_inbound_number
else form.sms_sender.data.replace("\r", ""),
sms_sender=(
sms_sender["sms_sender"]
if is_inbound_number
else form.sms_sender.data.replace("\r", "")
),
is_default=True if sms_sender["is_default"] else form.is_default.data,
)
return redirect(url_for(".service_sms_senders", service_id=service_id))

View File

@@ -16,10 +16,12 @@ from flask import (
url_for,
)
from flask_login import current_user
from notifications_utils.url_safe_token import generate_token
from app import login_manager, user_api_client
from app.main import main
from app.main.forms import LoginForm
from app.main.views.index import error
from app.main.views.verify import activate_user
from app.models.user import InvitedUser, User
from app.utils import hide_from_search_engines
@@ -53,22 +55,19 @@ def _get_access_token(code, state):
# JWT expiration time (10 minute maximum)
"exp": int(time.time()) + (10 * 60),
}
current_app.logger.warning(f"Here is the raw payload {payload}")
token = jwt.encode(payload, keystring, algorithm="RS256")
base_url = f"{access_token_url}?"
cli_assert = f"client_assertion={token}"
cli_assert_type = "client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"
code_param = f"code={code}"
url = f"{base_url}{cli_assert}&{cli_assert_type}&{code_param}&grant_type=authorization_code"
current_app.logger.info(f"This is the url we use to get the access token: {url}")
headers = {"Authorization": "Bearer %s" % token}
response = requests.post(url, headers=headers)
current_app.logger.info(f"GOT A RESPONSE {response.json()}")
access_token = response.json()["access_token"]
return access_token
def _get_user_email(access_token):
def _get_user_email_and_uuid(access_token):
headers = {"Authorization": "Bearer %s" % access_token}
user_info_url = os.getenv("LOGIN_DOT_GOV_USER_INFO_URL")
user_attributes = requests.get(
@@ -76,24 +75,28 @@ def _get_user_email(access_token):
headers=headers,
)
user_email = user_attributes.json()["email"]
return user_email
user_uuid = user_attributes.json()["sub"]
return user_email, user_uuid
@main.route("/sign-in", methods=(["GET", "POST"]))
@hide_from_search_engines
def sign_in():
def _do_login_dot_gov():
# start login.gov
code = request.args.get("code")
state = request.args.get("state")
login_gov_error = request.args.get("error")
if code and state:
access_token = _get_access_token(code, state)
user_email = _get_user_email(access_token)
user_email, user_uuid = _get_user_email_and_uuid(access_token)
redirect_url = request.args.get("next")
# activate the user
user = user_api_client.get_user_by_email(user_email)
activate_user(user["id"])
try:
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
activate_user(user["id"])
except BaseException as be: # noqa B036
current_app.logger.error(be)
error(401)
return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url))
elif login_gov_error:
@@ -101,6 +104,11 @@ def sign_in():
raise Exception(f"Could not login with login.gov {login_gov_error}")
# end login.gov
@main.route("/sign-in", methods=(["GET", "POST"]))
@hide_from_search_engines
def sign_in():
_do_login_dot_gov()
redirect_url = request.args.get("next")
if os.getenv("NOTIFY_E2E_TEST_EMAIL"):
@@ -167,40 +175,26 @@ def sign_in():
)
other_device = current_user.logged_in_elsewhere()
notify_env = os.getenv("NOTIFY_ENVIRONMENT")
current_app.logger.info("should render the sign in template")
# TODO REMOVE THIS INFO ONCE STAGING WORKS WITH LOGIN DOT GOV
current_app.logger.info(f"NOTIFY ENV = {notify_env}")
current_app.logger.info(
f"LOGIN_DOT_GOV_CLIENT_ID={os.getenv('LOGIN_DOT_GOV_CLIENT_ID')}"
token = generate_token(
str(request.remote_addr),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
current_app.logger.info(
f"LOGIN_DOT_GOV_USER_INFO_URL={os.getenv('LOGIN_DOT_GOV_USER_INFO_URL')}"
)
current_app.logger.info(
f"LOGIN_DOT_GOV_ACCESS_TOKEN_URL={os.getenv('LOGIN_DOT_GOV_ACCESS_TOKEN_URL')}"
)
current_app.logger.info(
f"LOGIN_DOT_GOV_LOGOUT_URL={os.getenv('LOGIN_DOT_GOV_LOGOUT_URL')}"
)
current_app.logger.info(
f"LOGIN_DOT_GOV_BASE_LOGOUT_URL={os.getenv('LOGIN_DOT_GOV_BASE_LOGOUT_URL')}"
)
current_app.logger.info(
f"LOGIN_DOT_GOV_SIGNOUT_REDIRECT={os.getenv('LOGIN_DOT_GOV_SIGNOUT_REDIRECT')}"
)
initial_signin_url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
current_app.logger.info(f"LOGIN_DOT_GOV_INITIAL_SIGNIN_URL={initial_signin_url}")
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
# handle unit tests
if url is not None:
url = url.replace("NONCE", token)
url = url.replace("STATE", token)
return render_template(
"views/signin.html",
form=form,
again=bool(redirect_url),
other_device=other_device,
login_gov_enabled=bool(notify_env in ["development", "staging"]),
login_gov_enabled=True,
password_reset_url=password_reset_url,
initial_signin_url=initial_signin_url,
initial_signin_url=url,
)

View File

@@ -6,10 +6,6 @@ from flask_login import current_user
from app.main import main
# ask login.gov if we really need manual logout and what's up with one hour sessions
# ask login.gov how they recommend approaching dev environment
# ask Tim Donaworth the same for #2
def _sign_out_at_login_dot_gov():
base_url = os.getenv("LOGIN_DOT_GOV_BASE_LOGOUT_URL")

View File

@@ -18,10 +18,6 @@ def features_nav():
"name": "Security",
"link": "main.security",
},
{
"name": "Terms of use",
"link": "main.terms",
},
]

View File

@@ -5,6 +5,7 @@ from itsdangerous import SignatureExpired
from notifications_utils.url_safe_token import check_token
from app import user_api_client
from app.extensions import redis_client
from app.main import main
from app.main.forms import TwoFactorForm
from app.models.user import InvitedOrgUser, InvitedUser, User
@@ -64,20 +65,46 @@ def verify_email(token):
def activate_user(user_id):
user = User.from_id(user_id)
# the user will have a new current_session_id set by the API - store it in the cookie for future requests
# This is the login.gov path
login_gov_invite_data = redis_client.get(f"service-invite-{user.email_address}")
if login_gov_invite_data:
login_gov_invite_data = json.loads(login_gov_invite_data.decode("utf8"))
# This is the deprecated path for organization invites where we get id from session
session["current_session_id"] = user.current_session_id
organization_id = session.get("organization_id")
activated_user = user.activate()
activated_user.login()
# TODO when login.gov is mandatory, get rid of the if clause, it is deprecated.
invited_user = InvitedUser.from_session()
if invited_user:
service_id = _add_invited_user_to_service(invited_user)
return redirect(url_for("main.service_dashboard", service_id=service_id))
elif login_gov_invite_data:
service_id = login_gov_invite_data["service_id"]
user.add_to_service(
service_id,
login_gov_invite_data["permissions"],
login_gov_invite_data["folder_permissions"],
login_gov_invite_data["from_user_id"],
)
return redirect(url_for("main.service_dashboard", service_id=service_id))
# TODO when login.gov is mandatory, git rid of the if clause, it is deprecated.
invited_org_user = InvitedOrgUser.from_session()
if invited_org_user:
user_api_client.add_user_to_organization(invited_org_user.organization, user_id)
elif redis_client.get(f"organization-invite-{user.email_address}"):
organization_id = redis_client.raw_get(
f"organization-invite-{user.email_address}"
)
user_api_client.add_user_to_organization(
organization_id.decode("utf8"), user_id
)
if organization_id:
return redirect(url_for("main.organization_dashboard", org_id=organization_id))

View File

@@ -45,7 +45,6 @@ class HeaderNavigation(Navigation):
"features_sms",
"roadmap",
"security",
"terms",
},
"using_notify": {
"get_started",

View File

@@ -44,6 +44,16 @@ class UserApiClient(NotifyAdminAPIClient):
user_data = self.post("/user/email", data={"email": email_address})
return user_data["data"]
def get_user_by_uuid_or_email(self, user_uuid, email_address):
user_data = self.post(
"/user/get-login-gov-user",
data={"login_uuid": user_uuid, "email": email_address},
)
if user_data is None or user_data.get("data") is None:
return None
return user_data["data"]
def get_user_by_email_or_none(self, email_address):
try:
return self.get_user_by_email(email_address)

View File

@@ -21,7 +21,7 @@
{% endblock %}
{% block meta %}
<meta property="og:site_name" content="Notify.gov">
<meta property="og:image" content="{{ asset_url('images/usa-opengraph-image.png') }}">
<meta property="og:image" content="{{ asset_url('images/notify-og-image.png') }}">
{% endblock %}
<script type="text/javascript" src="{{ asset_url('js/gtm_head.js') }}"></script>
{% endblock %}
@@ -175,11 +175,13 @@
{% endblock %}
{% block footer %}
<!-- lines 179 - 251 can all be deleted and replaced with {% include "new/components/footer.html" %} -->
{% if current_service and current_service.research_mode %}
{% set meta_suffix = 'Built by the <a href="https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions" class="usa-link">Technology Transformation Services</a><span id="research-mode" class="research-mode">research mode</span>' %}
{% else %}
{% set meta_suffix = 'Built by the <a href="https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions" class="usa-link">Technology Transformation Services</a>' %}
{% set commit_hash = ", Latest version: " + config['COMMIT_HASH'] %}
{% set long_link = '<a href="https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions" class="usa-link">Technology Transformation Services</a>' %}
{% set meta_suffix = "Built by the " + long_link + commit_hash %}
{% endif %}
{{ usaFooter({
@@ -201,10 +203,6 @@
"href": url_for("main.security"),
"text": "Security"
},
{
"href": url_for("main.terms"),
"text": "Terms of use"
},
]
},
{
@@ -244,7 +242,7 @@
{
"href": url_for('main.support'),
"text": "Contact us"
},
}
]
},
],
@@ -253,7 +251,6 @@
"html": meta_suffix
}
}) }}
{% if current_user.is_authenticated %}
{% block sessionUserWarning %}
<dialog class="usa-modal" id="sessionTimer" aria-labelledby="sessionTimerHeading" aria-describedby="timerWarning">

View File

@@ -4,38 +4,6 @@
</div> #}
<div class="usa-footer__primary-section">
<div class="grid-container">
<div class="grid-row">
<div class="grid-col">
{# {% if params.navigation %}
<nav class="usa-footer__nav" aria-label="Footer navigation,,">
<div class="grid-row grid-gap-2">
{% for nav in params.navigation %}
<div class="mobile-lg:grid-col-6 desktop:grid-col-4">
<section class="
usa-footer__primary-content
usa-footer__primary-content--collapsible
">
<h4 class="usa-footer__primary-link">{{ nav.title }}</h4>
<ul class="usa-list usa-list--unstyled">
{% for item in nav.items %}
{% if item.href and item.text %}
<li class="usa-footer__secondary-link">
<a href="{{ item.href }}" {% for attribute, value in item.attributes %}
{{attribute}}="{{value}}" {% endfor %}>
{{ item.text }}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</section>
</div>
{% endfor %}
</div>
</nav>
{% endif %} #}
</div>
</div>
<div class="padding-y-1">
{% if params.meta %}
<h2 class="usa-sr-only">{{ params.meta.visuallyHiddenTitle | default("Support links") }}</h2>
@@ -114,4 +82,4 @@
<a href="https://www.usa.gov/" class="usa-link">Visit USA.gov</a>
</div>
</section>
</div>
</div>

View File

@@ -44,61 +44,62 @@
<!-- usa header -->
<header class="usa-header usa-header--extended">
<div class="usa-navbar">
<div class="usa-logo display-flex flex-align-center" id="-logo">
{# <div class="logo-img display-flex">
<span class="usa-sr-only">US Notify Logo</span>
<image src="{{ params.assetsPath | default('/static/images') }}/us-notify-color.png" alt="US Notify logo" xlink:href=""
class="usa-flag-logo margin-right-1" width="40" height="35"></image>
</div> #}
<em class="logo-text usa-logo__text">
<a href="/" title="notify.gov">notify.gov</a>
</em>
</div>
{% if current_user.is_authenticated %}
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %}
</div>
<nav aria-label="Primary navigation" class="usa-nav">
<div class="usa-nav__inner">
<button type="button" class="usa-nav__close">
<img src="/static/images/usa-icons/close.svg" role="img" alt="Close" />
</button>
<ul class="usa-nav__primary usa-accordion margin-right-1">
{% for item in params.navigation %}
{% if item.href and item.text %}
<li class="usa-nav__primary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<div class="usa-nav__secondary margin-bottom-2">
<ul class="usa-nav__secondary-links">
{% for item in params.secondaryNavigation %}
{% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<!-- <section aria-label="Search component">
<form class="usa-search usa-search--small margin-bottom-2" role="search">
<label class="usa-sr-only" for="search-field">Search</label>
<input class="usa-input" id="search-field" type="search" name="search" />
<button class="usa-button" type="submit">
<img src="/static/images/usa-icons-bg/search--white.svg" class="usa-search__submit-icon" alt="Search" />
</button>
</form>
</section> -->
<div class="usa-nav-container">
<div class="usa-navbar">
<div class="usa-logo display-flex flex-align-center flex-justify" id="-logo">
<div class="logo-img display-flex">
<a href="/">
<span class="usa-sr-only">Notify.gov logo</span>
<image src="{{ params.assetsPath | default('/static/images') }}/notify-logo.png" alt="Notify.gov logo" xlink:href=""
class="usa-flag-logo margin-right-1"></image>
</a>
</div>
{% if params.navigation %}
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %}
</div>
</div>
</nav>
<nav aria-label="Primary navigation" class="usa-nav">
<div class="usa-nav__inner">
<button type="button" class="usa-nav__close">
<img src="/static/images/usa-icons/close.svg" role="img" alt="Close" />
</button>
<ul class="usa-nav__primary usa-accordion margin-right-1">
{% for item in params.navigation %}
{% if item.href and item.text %}
<li class="usa-nav__primary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<div class="usa-nav__secondary margin-bottom-6">
<ul class="usa-nav__secondary-links">
{% for item in params.secondaryNavigation %}
{% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<!-- <section aria-label="Search component">
<form class="usa-search usa-search--small margin-bottom-2" role="search">
<label class="usa-sr-only" for="search-field">Search</label>
<input class="usa-input" id="search-field" type="search" name="search" />
<button class="usa-button" type="submit">
<img src="/static/images/usa-icons-bg/search--white.svg" class="usa-search__submit-icon" alt="Search" />
</button>
</form>
</section> -->
</div>
</div>
</nav>
</div>
</header>

View File

@@ -0,0 +1,13 @@
# Select
## Installation
See the [main README quick start guide](https://github.com/alphagov/govuk-frontend#quick-start) for how to install this component.
## Guidance and Examples
Find out when to use the select component in your service in the [GOV.UK Design System](https://design-system.service.gov.uk/components/select/).
## Component options
Use options to customize the appearance, content and behavior of a component when using a macro, for example, changing the text.

View File

@@ -0,0 +1,58 @@
[
{
"name": "id",
"type": "string",
"required": true,
"description": "ID for each select box."
},
{
"name": "name",
"type": "string",
"required": true,
"description": "Name property for the select."
},
{
"name": "items",
"type": "array",
"required": true,
"description": "The items within the select component."
},
{
"name": "value",
"type": "string",
"required": false,
"description": "Value for the option which should be selected. Use this as an alternative to setting the selected option on each individual item."
},
{
"name": "disabled",
"type": "boolean",
"required": false,
"description": "If true, select box will be disabled. Use the disabled option on each individual item to only disable certain options."
},
{
"name": "describedBy",
"type": "string",
"required": false,
"description": "One or more element IDs to add to the `aria-describedby` attribute, used to provide additional descriptive information for screenreader users."
},
{
"name": "label",
"type": "object",
"required": true,
"description": "The label used by the select component.",
"isComponent": true
},
{
"name": "hint",
"type": "object",
"required": false,
"description": "Can be used to add a hint to the select component.",
"isComponent": true
},
{
"name": "classes",
"type": "string",
"required": false,
"description": "Classes to add to the select."
}
]

View File

@@ -0,0 +1,3 @@
{% macro usaSelect(params) %}
{%- include "./template.njk" -%}
{% endmacro %}

View File

@@ -0,0 +1,15 @@
{% set describedBy = params.describedBy if params.describedBy else "" %}
<div class="usa-form-group">
<label class="usa-label" for="{{ params.name }}">{{params.label}}</label>
{% if params.hint %}
<div class="usa-hint" id="{{ params.describedBy }}">{{ params.hint }}</div>
{% endif %}
<select class="usa-select {%- if params.classes %} {{ params.classes }}{% endif %}" id="{{ params.id }}" name="{{ params.name }}"
{%- if params.value %} value="{{ params.value}}"{% endif %}
{%- if describedBy %} aria-describedby="{{ describedBy }}"{% endif %}
{%- for attribute, value in params.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}>
{% for item in params.items %}
<option value="{{ item.value }}" {%- if item.disabled == true %} selected disabled {% endif %}>{{ item.text }}</option>
{% endfor %}
</select>
</div>

View File

@@ -171,8 +171,8 @@
{% endif %}
<p class="status-hint margin-0 width-card ">
{{ notification.status|format_notification_status_as_time(
notification.created_at|format_datetime_short,
(notification.updated_at or notification.created_at)|format_datetime_short
notification.created_at|format_datetime_table,
(notification.sent_at or notification.created_at)|format_datetime_table
) }}
</p>
{% if displayed_on_single_line %}</span>{% endif %}

View File

@@ -11,10 +11,10 @@
<div class="grid-row">
{% if navigation_links %}
<div class="tablet:grid-col-2">
<div class="tablet:grid-col-2 margin-bottom-4">
{{ sub_navigation(navigation_links) }}
</div>
<div class="tablet:grid-col-10 padding-left-4 usa-prose site-prose">
<div class="tablet:grid-col-10 tablet:padding-left-4 usa-prose site-prose">
{% else %}
<div class="tablet:grid-col-10">
{% endif %}

View File

@@ -4,6 +4,7 @@
<div class="grid-row">
<div class="grid-col-8">
<h1>Youre not authorized to see this page</h1>
<p class="usa-body"><a class="usa-link" href="{{ url_for('main.sign_in' )}}">Sign in</a> to Notify.gov and try again.</p>
<p class="usa-body">If you have been invited to join Notify.gov, <a class="usa-link" href="{{ url_for('main.sign_in' )}}">sign in</a> to Notify.gov using your Login.gov account and try again.</p>
</div>
{% endblock %}
e

View File

@@ -1,7 +1,7 @@
{% if help %}
{% include 'partials/tour.html' %}
{% else %}
<nav class="nav">
<nav class="nav margin-bottom-4">
<a class="usa-button margin-top-1 margin-bottom-5 width-full"
href="{{ url_for('.choose_template', service_id=current_service.id) }}">Send messages</a>
<ul class="usa-sidenav">
@@ -14,7 +14,7 @@
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
{% endif %}
{% if current_user.has_permissions('manage_service', allow_org_user=True) %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('usage') }}" href="{{ url_for('.usage', service_id=current_service.id) }}">Usage</a></li>
{# <li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('usage') }}" href="{{ url_for('.usage', service_id=current_service.id) }}">Usage</a></li> #}
{% endif %}
<!-- {% if current_user.has_permissions('manage_api_keys', 'manage_service') %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('settings') }}" href="{{ url_for('.service_settings', service_id=current_service.id) }}">Settings</a></li>

View File

@@ -19,17 +19,22 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
{% block headIcons %}
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{ assetPath | default('/assets') }}/images/favicon.ico" type="image/x-icon" />
<link rel="mask-icon" href="{{ assetPath | default('/assets') }}/images/usa-mask-icon.svg" color="{{ themeColor | default('#F0F0F0') }}">
<link rel="shortcut icon" href="{{ assetPath | default('/assets') }}/images/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32"href="{{ assetPath | default('/assets') }}/images/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="{{ assetPath | default('/assets') }}/images/favicon-16x16.png" />
<link rel="mask-icon" href="{{ assetPath | default('/assets') }}/images/safari-pinned-tab.svg" color="#5bbad5">
<link rel="apple-touch-icon" sizes="180x180" href="{{ assetPath | default('/assets') }}/images/apple-touch-icon.png">
<link rel="apple-touch-icon" href="{{ assetPath | default('/assets') }}/images/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<link href="{{ assetPath | default('/assets') }}/images/notify-dark-favicon.png" rel="icon" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff">
{% endblock %}
{% block head %}{% endblock %}
{# The default og:image is added below head so that scrapers see any custom metatags first, and this is just a fallback #}
{% block meta %}
<meta property="og:site_name" content="Notify.gov">
<meta property="og:image" content="{{ asset_url('images/usa-opengraph-image.png') }}">
<meta property="og:image" content="{{ asset_url('images/notify-og-image.png') }}">
{% endblock %}
</head>
<body class="usa-template__body {{ bodyClasses }}">

126
app/templates/new/base.html Normal file
View File

@@ -0,0 +1,126 @@
{% from "../components/banner.html" import banner %}
{% from "../components/components/skip-link/macro.njk" import usaSkipLink -%}
<!DOCTYPE html>
<html lang="{{ htmlLang | default('en') }}" class="{{ htmlClasses }}">
{% include "new/components/head.html" %}
<body class="usa-template__body {{ bodyClasses }}">
<script nonce="{{ csp_nonce() }}">document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
{% block bodyStart %}
{% block extra_javascripts_before_body %}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WX5NGWF"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{% endblock %}
{% endblock %}
{% block skipLink %}
{{ usaSkipLink({
"href": '#main-content',
"text": 'Skip to main content'
}) }}
{% endblock %}
{% block header %}
{% if current_user.is_authenticated %}
{% include 'new/components/usa_banner.html' %}
{% include 'new/components/header.html' %}
{% endif %}
{% endblock %}
{% block main %}
<div class="grid-container">
{% block beforeContent %}
{% block backLink %}{% endblock %}
{% endblock %}
{% block mainClasses %}
<!-- notes set mainClasses = "margin-top-5 padding-bottom-5" where withoutnav_template was used and maybe templates that are using content_template -->
<main class="{{ mainClasses }}" id="main-content" role="main">
{% endblock %}
{% block content %}
{% block flash_messages %}
<!-- flash_message.html was from the withoutnav_template and is only included on child templates that was using withoutnav_template. Now, we can add in flash_message blocks and include 'flash_messages.html' to child templates that was using withoutnav_template. This will help to eliminate the use of a whole other parent template. -->
{% endblock %}
{% block maincolumn_content %}
{% block fromContentTemplatetwoColumnGrid %}
<div class="grid-row">
{% if navigation_links %}
<div class="tablet:grid-col-2">
{{ sub_navigation(navigation_links) }}
</div>
<div class="tablet:grid-col-10 padding-left-4 usa-prose site-prose">
{% else %}
<div class="tablet:grid-col-10">
{% endif %}
{% block content_column_content %}{% endblock %}
</div>
</div>
<!-- content_column_content block is from the content_template.html. We do not need this template. We can consolidate and move it to the base.html template. We can call on this block where child templates were using the content_template.html -->
{% endblock %}
{% endblock %}
{% endblock %}
</main>
</div>
{% endblock %}
{% block footer %}
{% if current_service and current_service.research_mode %}
{% set meta_suffix = 'Built by the <a href="https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions" class="usa-link">Technology Transformation Services</a><span id="research-mode" class="research-mode">research mode</span>' %}
{% else %}
{% set commit_hash = ", Latest version: " + config['COMMIT_HASH'] %}
{% set long_link = '<a href="https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions" class="usa-link">Technology Transformation Services</a>' %}
{% set meta_suffix = "Built by the " + long_link + commit_hash %}
{% endif %}
{% include "new/components/footer.html" %}
{% if current_user.is_authenticated %}
{% block sessionUserWarning %}
<dialog class="usa-modal" id="sessionTimer" aria-labelledby="sessionTimerHeading" aria-describedby="timerWarning">
<div class="usa-modal__content">
<div class="usa-modal__main">
<h2 class="usa-modal__heading" id="sessionTimerHeading">
Your session will end soon.
<span class="usa-sr-only">Please choose to extend your session or sign out. Your session will expire in 5 minutes or less.</span>
</h2>
<div class="usa-prose">
<p>You have been inactive for too long.
Your session will expire in <span id="timeLeft" role="timer"></span>.
</p>
</div>
<div class="usa-modal__footer">
<ul class="usa-button-group">
<li class="usa-button-group__item">
<button type="button" class="usa-button" id="extendSessionTimer" data-close-modal>
Extend Session
</button>
</li>
<li class="usa-button-group__item">
<button type="button" class="usa-button usa-button--unstyled padding-105 text-center" id="logOutTimer"
data-close-modal>
Sign out
</button>
</li>
</ul>
</div>
</div>
</div>
</dialog>
{% endblock %}
{% endif %}
{% endblock %}
{% block bodyEnd %}
{% block extra_javascripts %}
{% endblock %}
<!--[if gt IE 8]><!-->
<script type="text/javascript" src="{{ asset_url('javascripts/all.js') }}"></script>
<script type="text/javascript" src="{{ asset_url('js/uswds.min.js') }}"></script>
<!--<![endif]-->
{% endblock %}
</body>
</html>

View File

@@ -0,0 +1,71 @@
<footer class="usa-footer usa-footer--big">
<div class="usa-footer__primary-section">
<div class="grid-container">
<div class="padding-y-1">
{% if meta_suffix %}
<h2 class="usa-sr-only">Support links</h2>
{% if meta_suffix %}
<div>
{{ meta_suffix | safe if meta_suffix else '' }}
</div>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
<div class="usa-identifier site-identifier">
<section class="usa-identifier__section usa-identifier__section--masthead" aria-label="Agency identifier,,,,,,">
<div class="usa-identifier__container">
<div class="usa-identifier__logos"><a href="javascript:void(0);" class="usa-identifier__logo">
<img class="usa-identifier__logo-img" src="{{ (asset_path | default('/static')) + 'images/gsa-logo.svg' }}" alt="GSA Logo" role="img" width="48" height="48">
</a></div>
<section class="usa-identifier__identity" aria-label="Agency description">
<p class="usa-identifier__identity-domain">beta.notify.gov</p>
<p class="usa-identifier__identity-disclaimer">An official website of the <a href="https://gsa.gov">General Services Administration</a></p>
</section>
</div>
</section>
<nav class="usa-identifier__section usa-identifier__section--required-links" aria-label="Important links">
<div class="usa-identifier__container">
<ul class="usa-identifier__required-links-list">
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/about-us" class="usa-identifier__required-link">About GSA</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/website-information/accessibility-aids"
class="usa-identifier__required-link">Accessibility support</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/reference/freedom-of-information-act-foia"
class="usa-identifier__required-link">FOIA requests</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/reference/civil-rights-programs/notification-and-federal-employee-antidiscrimination-and-retaliation-act-of-2002"
class="usa-identifier__required-link">No FEAR Act data</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsaig.gov/" class="usa-identifier__required-link">Office of the Inspector General</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/reference/reports/budget-performance"
class="usa-identifier__required-link">Performance reports</a>
</li>
<li class="usa-identifier__required-links-item">
<a href="https://www.gsa.gov/website-information/website-policies"
class="usa-identifier__required-link">Privacy policy</a>
</li>
</ul>
</div>
</nav>
<section class="usa-identifier__section usa-identifier__section--usagov"
aria-label="Government information and services">
<div class="usa-identifier__container">
<div class="usa-identifier__usagov-description">
Looking for U.S. government information and services?
</div>
<a href="https://www.usa.gov/" class="usa-link">Visit USA.gov</a>
</div>
</section>
</div>
</footer>

View File

@@ -0,0 +1,46 @@
<head>
<meta charset="utf-8" />
<title>{% block pageTitle %}Notify.gov{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Reach people where they are with a text message platform built just for government">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="f0f0f0" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="1b1b1b" />
{% if config['NR_MONITOR_ON'] %}
{% include "partials/newrelic.html" -%}
{% endif %}
{# Ensure that older IE versions always render with the correct rendering engine #}
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
{% block headIcons %}
<link rel="shortcut icon" href="{{ assetPath | default('/assets') }}/images/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="{{ assetPath | default('/assets') }}/images/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="{{ assetPath | default('/assets') }}/images/favicon-16x16.png" />
<link rel="mask-icon" href="{{ assetPath | default('/assets') }}/images/safari-pinned-tab.svg" color="#5bbad5">
<link rel="apple-touch-icon" sizes="180x180" href="{{ assetPath | default('/assets') }}/images/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<link href="{{ assetPath | default('/assets') }}/images/notify-dark-favicon.png" rel="icon" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff">
{% endblock %}
<link rel="stylesheet" media="screen" href="{{ asset_url('css/styles.css') }}" />
{% block extra_stylesheets %}{% endblock %}
{% block meta_format_detection %}
<meta name="format-detection" content="telephone=no">
{% endblock %}
{% block og_image %}
<meta property="og:title" content="Notify.gov">
<meta property="og:description" content="Reach people where they are with a text message platform built just for government">
<meta property="og:image" content="/static/images/notify-og-image.png">
{% endblock %}
{# google #}
<script type="text/javascript" src="{{ asset_url('js/gtm_head.js') }}"></script>
<meta name="google-site-verification" content="niWnSqImOWz6mVQTYqNb5tFK8HaKSB4b3ED4Z9gtUQ0" />
{% if g.hide_from_search_engines %}
<meta name="robots" content="noindex" />
{% endif %}
{% block head %}{% endblock %}
</head>

View File

@@ -0,0 +1,76 @@
{# setting navigation and secondarynavigation #}
{% set navigation = [
{"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active": header_navigation.is_selected('accounts-or-dashboard')},
{"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')},
{"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')},
{"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')}
] %}
{% if current_user.platform_admin %}
{% set navigation = navigation + [{"href": url_for('main.platform_admin_splash_page'), "text": "Platform admin", "active": header_navigation.is_selected('platform-admin')}] %}
{% else %}
{% set navigation = navigation + [{"href": url_for('main.user_profile'), "text": "User profile", "active": header_navigation.is_selected('user-profile')}] %}
{% endif %}
{% if current_service %}
{% set secondaryNavigation = [
{"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active": secondary_navigation.is_selected('settings')},
{"href": url_for('main.sign_out'), "text": "Sign out"}
] %}
{% else %}
{% set secondaryNavigation = [{"href": url_for('main.sign_out'), "text": "Sign out"}] %}
{% endif %}
{# usa header #}
<header class="usa-header usa-header--extended">
<div class="usa-nav-container">
<div class="usa-navbar">
<div class="usa-logo display-flex flex-align-center flex-justify" id="-logo">
<div class="logo-img display-flex">
<a href="/">
<span class="usa-sr-only">Notify.gov logo</span>
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.png' }}" alt="Notify.gov logo" class="usa-flag-logo margin-right-1">
</a>
</div>
{% if navigation %}
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %}
</div>
</div>
<nav aria-label="Primary navigation" class="usa-nav">
<div class="usa-nav__inner">
<button type="button" class="usa-nav__close">
<img src="/static/images/usa-icons/close.svg" role="img" alt="Close" />
</button>
<ul class="usa-nav__primary usa-accordion margin-right-1">
{% for item in navigation %}
{% if item.href and item.text %}
<li class="usa-nav__primary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<div class="usa-nav__secondary margin-bottom-6">
<ul class="usa-nav__secondary-links">
{% if secondaryNavigation %}
{% for item in secondaryNavigation %}
{% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
</ul>
</div>
</div>
</nav>
</div>
</header>

View File

@@ -0,0 +1,44 @@
{# usa banner #}
<section class="usa-banner site-banner" aria-label="Official website of the United States government,,,,,,">
<div class="usa-accordion">
<header class="usa-banner__header">
<div class="usa-banner__inner">
<div class="grid-col-auto">
<img aria-hidden="true" class="usa-banner__header-flag" src="/static/img/us_flag_small.png" alt="" />
</div>
<div class="grid-col-fill tablet:grid-col-auto" aria-hidden="true">
<p class="usa-banner__header-text">An official website of the United States government</p>
<p class="usa-banner__header-action">Heres how you know</p>
</div>
<button type="button" class="usa-accordion__button usa-banner__button" aria-expanded="false" aria-controls="gov-banner">
<span class="usa-banner__button-text">Heres how you know</span>
</button>
</div>
</header>
<div class="usa-banner__content usa-accordion__content" id="gov-banner" hidden="">
<div class="grid-row grid-gap-lg">
<div class="usa-banner__guidance tablet:grid-col-6">
<img class="usa-banner__icon usa-media-block__img" src="/static/img/icon-dot-gov.svg" role="img" alt="" aria-hidden="true">
<div class="usa-media-block__body">
<p>
<strong>Official websites use .gov</strong>
<br>
A <strong>.gov</strong> website belongs to an official government organization in the United States.
</p>
</div>
</div>
<div class="usa-banner__guidance tablet:grid-col-6">
<img class="usa-banner__icon usa-media-block__img" src="/static/img/icon-https.svg" role="img" alt="" aria-hidden="true">
<div class="usa-media-block__body">
<p>
<strong>Secure .gov websites use HTTPS</strong>
<br>
A <strong>lock</strong> ( <span class="icon-lock"><svg xmlns="http://www.w3.org/2000/svg" width="52" height="64" viewBox="0 0 52 64" class="usa-banner__lock-image" role="img" aria-labelledby="banner-lock-description" focusable="false"><title id="banner-lock-title">Lock</title><desc id="banner-lock-description">Locked padlock</desc><path fill="#000000" fill-rule="evenodd" d="M26 0c10.493 0 19 8.507 19 19v9h3a4 4 0 0 1 4 4v28a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V32a4 4 0 0 1 4-4h3v-9C7 8.507 15.507 0 26 0zm0 8c-5.979 0-10.843 4.77-10.996 10.712L15 19v9h22v-9c0-6.075-4.925-11-11-11z"></path></svg></span> ) or <strong>https://</strong> means youve safely connected to the .gov website. Share sensitive information only on official, secure websites.
</p>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@@ -0,0 +1,35 @@
{% extends "base.html" %}
{% block per_page_title %}
{% block org_page_title %}{% endblock %} {{ current_org.name }}
{% endblock %}
{% block main %}
<div class="grid-container">
<div class="navigation-service usa-breadcrumb">
{% if current_user.platform_admin %}
<a href="{{ url_for('.organizations') }}" class="usa-link navigation-organization-link">Organizations</a>
{% endif %}
<div class="navigation-service">
{{ current_org.name }}
</div>
<a href="{{ url_for('main.choose_account') }}" class="usa-link navigation-service">Switch service</a>
</div>
<div class="grid-row">
<div class="grid-col-3">
{% include "org_nav.html" %}
</div>
<div class="grid-col-9">
{% block beforeContent %}
{% block backLink %}{% endblock %}
{% endblock %}
<main class="main" id="main-content" role="main" >
{% block content %}
{% include 'flash_messages.html' %}
{% block maincolumn_content %}{% endblock %}
{% endblock %}
</main>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,41 @@
{% extends "base.html" %}
{% block per_page_title %}
{% block service_page_title %}{% endblock %} {{ current_service.name }}
{% endblock %}
{% block main %}
<div class="grid-container">
{% block serviceNavigation %}
{% include "service_navigation.html" %}
{% endblock %}
<!-- The withnav_template can be used to replace the settings_template. when it comes to setting_template and withnav_template, this service_navigation.html is only used in withnav_template and in settings_template, it was not used. That is one out of the two differences between settings template and withnav template. Child templates that extends settings_template, include the block serviceNavigation but leave it empty. Within the app, the only pages settings_template.html is used: manage-users.html, service-settings.html, and user-profile.html -->
<div class="grid-row margin-top-5">
{% if help %}
<div class="grid-col-3">
{% else %}
<div class="grid-col-3">
{% endif %}
{% block sideNavigation %}
{% include "main_nav.html" %}
<!-- include settings_nav.html for child templates that used settings_template -->
{% endblock %}
</div>
{% if help %}
<div class="grid-col-8">
{% else %}
<div class="grid-col-9 padding-left-4">
{% endif %}
{% block beforeContent %}
{% block backLink %}{% endblock %}
{% endblock %}
<main id="main-content" role="main" class="usa-prose site-prose margin-bottom-10">
{% block content %}
{% include 'flash_messages.html' %}
{% block maincolumn_content %}{% endblock %}
{% endblock %}
</main>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,38 @@
# New Templates Glossary
This document serves as a glossary for the templates directory structure of the project.
## Directory Structure
- `/templates`
- `base.html`: The main base template from which all other templates inherit. This template is a combination of `main_template`, `admin_template`, `withoutnav_template`, `settings_templates`, and `content_template`.
- **/layouts**: Contains shared layouts used across the site. Simply put, it defines the overall structure or skeleton of the application (less frequently revised).
- `withnav_template.html`: A variation of the base layout that includes a sidebar.
- `org_template.html`: A variaton of the withnav_template
- **/components**: Houses reusable UI components that can be included in multiple templates and can be tailored with different content or links depending on the context.(more frequently revised or customized)
- `head.html`: Template for the site's <head>, included in `base.html`.
- `header.html`: Template for the site's header, included in `base.html`.
- `footer.html`: Template for the site's footer, included in `base.html`.
- **/views** (or **/pages**): Individual page templates that use the base layouts, components, and partials to present content.
### Best Practices
- Use **inheritance** `{% extends %}` to build on base layouts.
- Employ **components** `{% include %}` for reusable UI elements to keep the code DRY and facilitate easier updates.
### Observation Notes
- The macro-options.json files in the header and footer component act as structural guides. They aren't directly used as data passed to the usaFooter function/macro. Instead, these files outline the expected properties and provide a description of their purpose. The `usaFooter` macro component is currently only invoked in the `admin_template`, which will eventually serve as the `base.html` template. This will simplify the approach when we change the footer macros to componenets by eliminating the need to dynamically pass this data from the base.html template. This is also true for `usaHeader` macro component.
### Old Layout Templates We Don't Need
- withoutnav_template.html Delete
- main_template.html Delete
- settings_templates.html `withnav_template` can be used to replace `settings_template`.
- settings_nav.html (move to /new/navigation directory)
- main_nav.html (move to /new/navigation directory)
- service_navigation.html (move to /new/navigation directory)
- org_template, could be under it's own directory called /layout/organization
- org_nav.html (move to /new/navigation directory)
- content_template.html Delete

View File

@@ -1,49 +1,7 @@
{% from "components/pill.html" import pill %}
<div class="ajax-block-container">
{% if notifications_deleted %}
<div class="grid-row ">
{% for label, query_param, url, count in counts %}
{% if query_param == 'pending' %}
<div class="grid-col-3">
<span class="big-number-smaller">
<span class="big-number-number">
{% if count is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, count) }}
{% else %}
{{ "{:,}".format(count) }}
{% endif %}
{% else %}
{{ count }}
{% endif %}
</span>
<span class="big-number-label">{{ query_param }}</span>
</span>
</div>
{% else %}
<div class="grid-col-3">
<span class="big-number-smaller">
<span class="big-number-number">
{% if count is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, count) }}
{% else %}
{{ "{:,}".format(count) }}
{% endif %}
{% else %}
{{ count }}
{% endif %}
</span>
<span class="big-number-label">{{ label }}</span>
</span>
</div>
{% endif %}
{% endfor %}
</div>
{% else %}
<div class="tabs">
{{ pill(counts, request.args.get('status', '')) }}
</div>
{% endif %}
<div class="tabs">
{{ pill(counts, request.args.get('status', '')) }}
</div>
</div>

View File

@@ -28,14 +28,14 @@
<p class="bottom-gutter hint">
Report is {{ "{:.0f}%".format(job.percentage_complete * 0.99) }} complete…
</p>
{% elif notifications %}
{% elif notifications and time_left != "Data no longer available" %}
<p class="bottom-gutter">
<a href="{{ download_link }}" download class="usa-link heading-small">Download this report (<abbr title="Comma separated values">CSV</abbr>)</a>
&emsp;
<span id="time-left">{{ time_left }}</span>
</p>
{% endif %}
{% call(item, row_number) list_table(
notifications,
caption=uploaded_file_name,

View File

@@ -1,13 +1,48 @@
{% set display_message_status %}
{% if job.template.content %}
<h2 class="sms-message-header">Message</h2>
<div class="sms-message-wrapper">{{ current_service.name }}: {{job.template.content}}</div>
{% endif %}
{% if job.original_file_name %}
<h2 class="recipient-list">Recipient list</h2>
<div>
<ul class="usa-icon-list">
<li class="usa-icon-list__item">
<img src="{{ url_for('static', filename='img/material-icons/description.svg') }}" alt="Description Icon">
<div class="usa-icon-list__content">
<h3>{{ job.original_file_name }}</h3>
</div>
</li>
</ul>
</div>
{% endif %}
<h2>Delivery Status</h2>
{% endset %}
<div class="ajax-block-container">
<p class='bottom-gutter'>
{% if job.scheduled_for %}
{% if job.processing_started %}
Sent by {{ job.created_by.name }} on {{ job.processing_started|format_datetime_short }}
{% if job.still_processing or arrived_from_preview_page_url %}
{% if job.scheduled_for %}
<div class="usa-alert usa-alert--info">
<div class="usa-alert__body">
<h4 class="usa-alert__heading">Your text has been scheduled</h4>
<p class="usa-alert__text">
{{ job.template_name }} - {{ current_service.name }} was scheduled on {{ job.scheduled_for|format_datetime_normal }} by {{ job.created_by.name }}
</p>
</div>
</div>
{{display_message_status}}
{% else %}
Uploaded by {{ job.created_by.name }} on {{ job.created_at|format_datetime_short }}
<div class="usa-alert usa-alert--success">
<div class="usa-alert__body">
<h4 class="usa-alert__heading">Your text has been sent</h4>
<p class="usa-alert__text">
{{ job.template_name }} - {{ current_service.name }} was sent on {{ job.created_at|format_datetime_normal }} by {{ job.created_by.name }}
</p>
</div>
</div>
{{display_message_status}}
{% endif %}
{% else %}
Sent by {{ job.created_by.name }} on {{ job.created_at|format_datetime_short }}
{% endif %}
</p>
{% if job.status == 'sending limits exceeded'%}

View File

@@ -1,7 +1,7 @@
{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading, notification_status_field %}
{% from "components/page-footer.html" import page_footer %}
<div class="ajax-block-container" aria-labelledby='pill-selected-item'>
<div class="ajax-block-container table-wrapper" aria-labelledby='pill-selected-item'>
<div class="dashboard-table bottom-gutter-3-2">
{% call(item, row_number) list_table(

View File

@@ -8,16 +8,16 @@
<div class="grid-container">
<div class="grid-row margin-top-5">
{% if help %}
<div class="grid-col-3">
<div class="tablet:grid-col-3">
{% else %}
<div class="grid-col-3">
<div class="tablet:grid-col-3 margin-bottom-4">
{% endif %}
{% include "settings_nav.html" %}
</div>
{% if help %}
<div class="grid-col-8">
<div class="tablet:grid-col-8">
{% else %}
<div class="grid-col-9 padding-left-4">
<div class="tablet:grid-col-9 tablet:padding-left-4">
{% endif %}
{% block beforeContent %}
{% block backLink %}{% endblock %}

View File

@@ -5,6 +5,7 @@
<div class="ajax-block-container" id='pill-selected-item'>
{% if notifications %}
<div class="table-wrapper">
<div class='dashboard-table'>
{% endif %}
{% call(item, row_number) list_table(
@@ -29,6 +30,7 @@
{% endcall %}
{% if notifications %}
</div>
</div>
{% endif %}
{% if show_pagination %}

View File

@@ -14,24 +14,26 @@
{% block maincolumn_content %}
{{ page_header('Callbacks') }}
<div class="bottom-gutter-3-2 dashboard-table body-copy-table">
{% call mapping_table(
caption='General',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False,
caption_visible=False
) %}
{% call row() %}
{{ text_field('Delivery receipts') }}
{{ optional_text_field(delivery_status_callback, truncate=true) }}
{{ edit_field('Change', url_for('.delivery_status_callback', service_id=current_service.id)) }}
{% endcall %}
<div class="table-wrapper">
<div class="bottom-gutter-3-2 dashboard-table body-copy-table">
{% call mapping_table(
caption='General',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False,
caption_visible=False
) %}
{% call row() %}
{{ text_field('Delivery receipts') }}
{{ optional_text_field(delivery_status_callback, truncate=true) }}
{{ edit_field('Change', url_for('.delivery_status_callback', service_id=current_service.id)) }}
{% endcall %}
{% call row() %}
{{ text_field('Received text messages') }}
{{ optional_text_field(received_text_messages_callback, truncate=true) }}
{{ edit_field('Change', url_for('.received_text_messages_callback', service_id=current_service.id)) }}
{% endcall %}
{% endcall %}
{% call row() %}
{{ text_field('Received text messages') }}
{{ optional_text_field(received_text_messages_callback, truncate=true) }}
{{ edit_field('Change', url_for('.received_text_messages_callback', service_id=current_service.id)) }}
{% endcall %}
{% endcall %}
</div>
</div>
{% endblock %}

View File

@@ -44,7 +44,7 @@
{% endcall %}
{% if item.expiry_date %}
{% call field(align='right') %}
<span class='hint'>Revoked {{ item.expiry_date|format_datetime_short }}</span>
<span class='hint'>Revoked {{ item.expiry_date|format_datetime_table }}</span>
{% endcall %}
{% else %}
{% call field(align='right', status='error') %}

View File

@@ -1,6 +1,5 @@
{% extends "withnav_template.html" %}
{% from "components/banner.html" import banner_wrapper %}
{% from "components/table.html" import list_table, field, text_field, index_field, hidden_field_heading %}
{% from "components/page-header.html" import page_header %}
{% from "components/components/button/macro.njk" import usaButton %}
{% from "components/components/skip-link/macro.njk" import usaSkipLink %}
@@ -9,7 +8,7 @@
{% set file_contents_header_id = 'file-preview' %}
{% block service_page_title %}
{{ "Preview of {}".format(template.name) }}
{{ "Select delivery time" }}
{% endblock %}
@@ -19,11 +18,11 @@
{% block maincolumn_content %}
{{ page_header('Preview of {}'.format(template.name)) }}
{{ page_header('Select delivery time') }}
{{ template|string }}
<div class="bottom-gutter-3-2">
<form method="post" enctype="multipart/form-data" action="{{url_for('main.start_job', service_id=current_service.id, upload_id=upload_id)}}" class='page-footer'>
<form method="post" enctype="multipart/form-data" action="{{url_for('main.preview_job', service_id=current_service.id, template_id=template_id, upload_id=upload_id)}}" class='page-footer'>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
{% if choose_time_form %}
{{ choose_time_form.scheduled_for(param_extensions={
@@ -37,55 +36,11 @@
{% endif %}
{% set button_text %}
Send {{ count_of_recipients|message_count(template.template_type) }}
Preview
{% endset %}
{{ usaButton({ "text": button_text }) }}
</form>
</div>
{% if not request.args.from_test %}
<h2 class="font-body-lg" id="{{ file_contents_header_id }}">{{ original_file_name }}</h2>
<div class="fullscreen-content" data-module="fullscreen-table">
{% call(item, row_number) list_table(
recipients.displayed_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="usa-sr-only">Row in file</span><span aria-hidden="true">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span>
{% if (item.index + 2) == preview_row %}
{{ item.index + 2 }}
{% else %}
<a class="usa-link" href="{{ url_for('.check_messages', service_id=current_service.id, template_id=template.id, upload_id=upload_id, row_index=(item.index + 2), original_file_name=original_file_name) }}">{{ item.index + 2 }}</a>
{% endif %}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item[column].ignore %}
{{ text_field(item[column].data or '', status='default') }}
{% else %}
{{ text_field(item[column].data or '') }}
{% endif %}
{% endfor %}
{% if item[None].data %}
{% for column in item[None].data %}
{{ text_field(column, status='default') }}
{% endfor %}
{% endif %}
{% endcall %}
</div>
{% endif %}
{% if count_of_displayed_recipients < count_of_recipients %}
<p class="table-show-more-link">
Only showing the first {{ count_of_displayed_recipients }} rows
</p>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,107 @@
{% extends "withnav_template.html" %}
{% from "components/banner.html" import banner_wrapper %}
{% from "components/table.html" import list_table, field, text_field, hidden_field_heading %}
{% from "components/page-header.html" import page_header %}
{% from "components/components/button/macro.njk" import usaButton %}
{% from "components/components/skip-link/macro.njk" import usaSkipLink %}
{% from "components/components/back-link/macro.njk" import usaBackLink %}
{% set file_contents_header_id = 'file-preview' %}
{% block service_page_title %}
{{ "Preview of {}".format(template.name) }}
{% endblock %}
{% block backLink %}
{{ usaBackLink({ "href": back_link_from_preview }) }}
{% endblock %}
{% block maincolumn_content %}
{{ page_header('Preview') }}
<div>
<p class="sms-message-scheduler">Scheduled: {{ scheduled_for |format_datetime_normal if scheduled_for else 'Now'}}</p>
<p class="sms-message-file-name">File: {{original_file_name}}</p>
<p class="sms-message-template">Template: {{template.name}}</p>
<p class="sms-message-sender" >From: {{ template.sender }}</p>
</div>
<h2 id="{{ file_contents_header_id }}">Message</h2>
<div class="preview-message"> {{ template|string }}</div>
{% if not request.args.from_test %}
<h2>Recipients list</h2>
<div>
<ul class="usa-icon-list">
<li class="usa-icon-list__item">
<img src="{{ url_for('static', filename='img/material-icons/description.svg') }}" alt="Description Icon">
<div class="usa-icon-list__content">
<h3>{{ original_file_name }}</h3>
</div>
</li>
</ul>
</div>
<div class="usa-table-container--scrollable" tabindex="0">
<table class="usa-table usa-table--borderless width-full">
<caption class="font-body-lg table-heading">
Note: Only the first 5 rows are displayed here.
</caption>
<thead class="table-field-headings-visible">
<tr>
{% for header in recipients.column_headers %}
<th scope="col" class="table-field-heading-first">
{{ header }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for item in recipients.displayed_rows %}
{% if loop.index <= 5 %}
<tr class="table-row">
{% for column in recipients.column_headers %}
<td class="table-field-left-aligned">
<div>
{% set column_data = item[column].data or '' %}
{% if column_data is iterable and column_data is not string %}
<ul>
{% for data_item in column_data %}
{% if data_item is not none %}
<li>{{ data_item }}</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
{{ column_data }}
{% endif %}
</div>
</td>
{% endfor %}
{% if item[None].data %}
{% for column in item[None].data %}
<td class="table-field-left-aligned">
<div class="">
{{ column }}
</div>
</td>
{% endfor %}
{% endif %}
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<!-- <div class="bottom-gutter-3-2">
<p>This is a placeholder: This message will be delivered to <b>400 phone numbers</b> and will use a total of <b>800 message parts</b>, leaving Washington DSHS with <b>249,200 message parts remaining</b>.</p>
</div> -->
<form method="post" enctype="multipart/form-data" action="{{url_for('main.start_job', service_id=current_service.id, upload_id=upload_id)}}" class='page-footer'>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<h3>Does everything look good?</h3>
{% set button_text %}
{{ "Schedule" if scheduled_for else 'Send'}}
{% endset %}
{{ usaButton({ "text": button_text }) }}
</form>
{% endblock %}

View File

@@ -1,115 +1,117 @@
{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading %}
<div class='dashboard-table ajax-block-container'>
{% call(item, row_number) list_table(
jobs,
caption="Recent files uploaded",
caption_visible=False,
empty_message=(
'You have not uploaded any files yet.'
),
field_headings=[
'File',
'Status'
],
field_headings_visible=False
) %}
{% call row_heading() %}
<div class="file-list">
<a class="file-list-filename-large usa-link" href="{{ url_for('.view_job', service_id=current_service.id, job_id=item.id) }}">{{ item.original_file_name }}</a>
{% if item.scheduled %}
<span class="file-list-hint-large">
Sending {{
item.scheduled_for|format_datetime_relative
}}
</span>
{% else %}
<span class="file-list-hint-large">
Sent {{
(item.scheduled_for or item.created_at)|format_datetime_relative
}}
</span>
{% endif %}
</div>
{% endcall %}
{% call field() %}
{% if item.scheduled %}
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
<span class="big-number-smallest">
<span class="big-number-number">
{% if item.notification_count is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, item.notification_count) }}
{% else %}
{{ "{:,}".format(item.notification_count) }}
{% endif %}
{% else %}
{{ item.notification_count }}
{% endif %}
</span>
{% if item.notification_count %}
<span class="big-number-label">{{ item.notification_count|message_count_label(item.template_type,suffix='waiting to send') }}</span>
{% endif %}
<div class="table-wrapper">
<div class='dashboard-table ajax-block-container'>
{% call(item, row_number) list_table(
jobs,
caption="Recent files uploaded",
caption_visible=False,
empty_message=(
'You have not uploaded any files yet.'
),
field_headings=[
'File',
'Status'
],
field_headings_visible=False
) %}
{% call row_heading() %}
<div class="file-list">
<a class="file-list-filename-large usa-link" href="{{ url_for('.view_job', service_id=current_service.id, job_id=item.id) }}">{{ item.original_file_name }}</a>
{% if item.scheduled %}
<span class="file-list-hint-large">
Sending {{
item.scheduled_for|format_datetime_relative
}}
</span>
{% if link %}
</a>
{% endif %}
{% else %}
<div class="grid-row">
<div class="grid-col-4">
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
{% else %}
<span class="file-list-hint-large">
Sent {{
(item.scheduled_for or item.created_at)|format_datetime_relative
}}
</span>
{% endif %}
</div>
{% endcall %}
{% call field() %}
{% if item.scheduled %}
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
<span class="big-number-smallest">
<span class="big-number-number">
{{ "{:,}".format(item.notifications_sending) }}
</span>
<span class="big-number-label">pending</span>
</span>
{% if link %}
</a>
{% endif %}
</div>
<div class="grid-col-4">
<span class="big-number-smallest">
<span class="big-number-number">
{% if item.notifications_delivered is number %}
{{ "{:,}".format(item.notifications_delivered) }}
{% else %}
{{ item.notifications_delivered }}
{% endif %}
</span>
<span class="big-number-label">delivered</span>
</span>
</div>
<div class="grid-col-4">
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
<span class="big-number-smallest">
<span class="big-number-number">
{% if item.notifications_failed is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, item.notifications_failed) }}
{% if item.notification_count is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, item.notification_count) }}
{% else %}
{{ "{:,}".format(item.notification_count) }}
{% endif %}
{% else %}
{{ "{:,}".format(item.notifications_failed) }}
{{ item.notification_count }}
{% endif %}
{% else %}
{{ item.notifications_failed }}
</span>
{% if item.notification_count %}
<span class="big-number-label">{{ item.notification_count|message_count_label(item.template_type,suffix='waiting to send') }}</span>
{% endif %}
</span>
<span class="big-number-label">failed</span>
{% if link %}
</a>
{% endif %}
{% else %}
<div class="grid-row">
<div class="grid-col-4">
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
<span class="big-number-smallest">
<span class="big-number-number">
{{ "{:,}".format(item.notifications_sending) }}
</span>
<span class="big-number-label">pending</span>
</span>
{% if link %}
</a>
{% endif %}
</div>
<div class="grid-col-4">
<span class="big-number-smallest">
<span class="big-number-number">
{% if item.notifications_delivered is number %}
{{ "{:,}".format(item.notifications_delivered) }}
{% else %}
{{ item.notifications_delivered }}
{% endif %}
</span>
<span class="big-number-label">delivered</span>
</span>
{% if link %}
</a>
</div>
<div class="grid-col-4">
{% if link %}
<a class="usa-link display-flex" href="{{ link }}">
{% endif %}
<span class="big-number-smallest">
<span class="big-number-number">
{% if item.notifications_failed is number %}
{% if currency %}
{{ "{}{:,.2f}".format(currency, item.notifications_failed) }}
{% else %}
{{ "{:,}".format(item.notifications_failed) }}
{% endif %}
{% else %}
{{ item.notifications_failed }}
{% endif %}
</span>
<span class="big-number-label">failed</span>
</span>
{% if link %}
</a>
{% endif %}
</div></div>
{% endif %}
</div></div>
{% endif %}
{% endcall %}
{% endcall %}
{% endcall %}
</div>
</div>

View File

@@ -1,43 +1,25 @@
<div class="ajax-block-container">
<div class="grid-row grid-gap">
<div id="total-sms" class="grid-col-12">
<span class="big-number-with-status">
<a class="usa-link display-flex" href="{{ url_for('.view_notifications', service_id=service_id, message_type='sms', status='sending,delivered,failed') }}">
<div id="total-sms" class="grid-col-12 margin-top-2">
<span class="big-number-with-status display-block margin-bottom-2">
<p>
<span class="big-number-smaller">
<span class="big-number-number">
{% if statistics['sms']['requested'] is number %}
{{ "{:,}".format(statistics['sms']['requested']) }}
{{ "{:,}".format(statistics['sms']['requested']) }}
{% else %}
{{ statistics['sms']['requested'] }}
{{ statistics['sms']['requested'] }}
{% endif %}
</span>
<span class="big-number-label">{{ statistics['sms']['requested']|message_count_label('sms', suffix='sent') }}</span>
<span class="big-number-label">{{ statistics['sms']['requested']|message_count_label('sms', suffix='sent') }} in the last seven days</span>
</span>
</p>
<a class="usa-button usa-button--outline" href="{{ url_for('.view_notifications', service_id=service_id, message_type='sms', status='sending,delivered,failed') }}">
Details
</a>
{% if show_failures %}
<span class="big-number-status{% if statistics['sms']['show_warning'] is sameas true %} big-number-status--failing{% endif %}">
{% if statistics['sms']['failed'] %}
<a class="usa-link" href="{{ url_for('.view_notifications', service_id=service_id, message_type='sms', status='failed') }}">
{{ "{:,}".format(statistics['sms']['failed']) }}
failed {{ statistics['sms']['failed_percentage'] }}%
</a>
{% else %}
No failures
{% endif %}
</span>
{% endif %}
{# Removing the failures area for now, as the user can click on the above link to see all the details.
In the future state of the dashboard, the all statuses will be more apparent with data visualizations #}
</span>
</div>
<!-- <div id="total-email" class="grid-col-6">
<span class="big-number-with-status pilot-disabled">
<a class="usa-link display-block margin-bottom-1">
<span class="big-number-smaller">
<span class="big-number-number">0</span>
<span class="big-number-label">emails sent</span>
</span>
</a>
<span class="big-number-status">No failures</span>
</span>
</div> -->
</div>
</div>

View File

@@ -7,7 +7,7 @@
</caption>
<thead>
<tr>
<th scope="col">Usage</th>
<th scope="col">Sent</th>
<th scope="col">Remaining</th>
</tr>
</thead>

View File

@@ -18,92 +18,93 @@
{{ ajax_block(partials, updates_url, 'upcoming') }}
<h2 class="font-body-xl margin-0">
<h2 class="font-body-2xl line-height-sans-2 margin-0">
Messages sent
</h2>
<p class="margin-top-0">In the last seven days</p>
{{ ajax_block(partials, updates_url, 'inbox') }}
{{ ajax_block(partials, updates_url, 'totals') }}
{{ ajax_block(partials, updates_url, 'template-statistics') }}
<h2 class="margin-top-4 margin-bottom-1">Batched Jobs</h2>
<div class='job-table'>
{% call(item, row_number) list_table(
notifications,
caption="Batched Jobs",
caption_visible=False,
border_visible=True,
empty_message='No batched job messages found &thinsp;(messages are kept for {} days)'.format(service_data_retention_days)|safe,
field_headings=['Template Name','Date/Time', 'Download (CSV) Report'],
field_headings_visible=False
) %}
{% if item.job.original_file_name and item.job.id %}
{% call row_heading() %}
<a class="usa-link file-list-filename" href="/services/{{ item.service }}/jobs/{{ item.job.id }}">{{ item.job.original_file_name|replace('.csv', '') if item.job.id else '' }}</a>
{% endcall %}
{% call row_heading() %}
{{ item.status|format_notification_status_as_time(
item.created_at|format_datetime_short,
(item.updated_at or item.created_at)|format_datetime_short)
}}
{% endcall %}
{% call row_heading() %}
{% set availability = download_availability|selectattr('job_id', 'equalto', item.job.id)|first %}
{% if availability and availability.time_left != "Data no longer available" %}
<a class="usa-link file-list-filename" href="{{ availability.download_link[0] }}">{{ "Download" if item.job.original_file_name else '' }}</a>
<span>- {{ availability.time_left }}</span>
{% elif availability %}
<span>{{ availability.time_left }}</span>
<h2 class="margin-top-4 margin-bottom-1">Recent Batches</h2>
<div class="table-wrapper">
<table class="usa-table usa-table--borderless job-table">
<thead class="table-field-headings">
<tr>
<th scope="col" class="table-field-heading-first">
<span>File name</span>
</th>
<th scope="col" class="table-field-heading">
<span>Template</span>
</th>
<th scope="col" class="table-field-heading">
<span>Time sent</span>
</th>
<th scope="col" class="table-field-heading">
<span>Sender</span>
</th>
<th scope="col" class="table-field-heading">
<span># of Recipients</span>
</th>
<th scope="col" class="table-field-heading">
<span>Report</span>
</th>
</tr>
</thead>
<tbody>
{% if job_and_notifications %}
{% for job in job_and_notifications[:5] %}
{% if job.job_id and job.notifications %}
{% set notification = job.notifications[0] %}
<tr class="table-row" id="{{ job.job_id }}">
<td class="table-field file-name">
{{ notification.job.original_file_name if notification.job.original_file_name else 'Manually entered number'}}
<br>
<a class="usa-link file-list-filename" href="{{ job.view_job_link }}">View Batch</a>
</td>
<td class="table-field template">
{{ notification.template.name }}
</td>
<td class="table-field time-sent">
{{ job.created_at | format_datetime_table }}
</td>
<td class="table-field sender">
{{ notification.created_by.name }}
</td>
<td class="table-field count-of-recipients">
{{ job.notification_count}}
</td>
<td class="table-field report">
{% if notification and job.time_left != "Data no longer available" %}
<a class="usa-link file-list-filename" href="{{ job.download_link }}">Download</a>
<span class="usa-hint">{{ job.time_left }}</span>
{% elif job %}
<span>{{ job.time_left }}</span>
{% endif %}
</td>
</tr>
{% endif %}
{% endcall %}
{% endfor %}
{% else %}
<tr class="table-row">
<td class="table-empty-message" colspan="10">No batched job messages found &thinsp;(messages are kept for {{ service_data_retention_days }} days).</td>
</tr>
{% endif %}
{% endcall %}
</tbody>
</table>
</div>
{% if show_pagination %}
{{ previous_next_navigation(prev_page, next_page) }}
{% elif next_page %}
<p class="table-show-more-link">
Only showing the first 50 messages
</p>
{% endif %}
<h2 class="margin-top-4 margin-bottom-1">Usage</h2>
<h3 class="margin-bottom-0">Daily</h3>
<p class="margin-0">Across all services</p>
<table class="usage-table usa-table usa-table--borderless margin-top-1 margin-bottom-5">
<caption class="usa-sr-only">
Daily
</caption>
<thead>
<tr>
<th scope="col">Usage</th>
<th scope="col">Remaining</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ global_message_limit - daily_global_messages_remaining }}</td>
<td>
{{ daily_global_messages_remaining }}
</td>
</tr>
</tbody>
</table>
<h2 class="margin-top-4 margin-bottom-1">Message count</h2>
{% if current_user.has_permissions('manage_service') %}
<h3 class='margin-bottom-0' id="current-year"></h3>
{{ ajax_block(partials, updates_url, 'usage') }}
<a
href="{{ url_for('.usage', service_id=current_service['id']) }}"
class="usa-link show-more"
><span>See all usage</span></a>
<p class="margin-top-0">During the pilot period, each service has an allowance of 250,000 message parts. Once this allowance is met, the
application will stop delivering messages. There's no monthly charge, no setup fee, and no procurement cost.</p>
<p class="align-with-heading-copy">
What counts as 1 text message part?<br />
See <a class="usa-link" href="{{ url_for('.pricing') }}">pricing</a>.
</p>
{% endif %}
</div>

View File

@@ -11,115 +11,232 @@
<h1 class="font-body-2xl margin-bottom-3">Guidance</h1>
<p>This guidance is for teams using Notify.gov to send text messages.</p>
<p>It explains how to:</p>
<p>Notify allows you easily to create templates for messages for your recipients. You can customize messages to encourage
your recipient to manage their benefits and increase follow through.</p>
<p>Below we explain how to:</p>
<ul class="list list-bullet">
<li><a class="usa-link" href="#editandformat">edit and format messages</a></li>
<li><a class="usa-link" href="#customization">add customization</a></li>
<!-- <li><a class="usa-link" href="{{ url_for('.send_files_by_email') }}">send files by email</a></li> -->
<li><a class="usa-link" href="#format-content">Format your content</a></li>
<li><a class="usa-link" href="#add-links">Add links</a></li>
<li><a class="usa-link" href="#personalize-content">Personalize your content</a></li>
<li><a class="usa-link" href="#conditional-content">Add conditional content</a></li>
<li><a class="usa-link" href="#indentify-program">Identify your program</a></li>
<li><a class="usa-link" href="#prepare-data">Prepare your data</a></li>
<li><a class="usa-link" href="#prevent-fraud">Prevent fraud</a></li>
</ul>
<h2 class="font-body-lg" id="#formatting">Edit and format messages</h2>
{# Format content #}
<h2 class="padding-top-1" id="format-content">Format your content</h2>
<p>Effective texts will help your message recipients take the steps needed to secure and keep the benefits and services
they depend on. To craft an effective text:</p>
<p>This section explains how to:</p>
<ul class="list list-bullet">
<li><a class="usa-link" href="#formatting">format your content</a></li>
<li><a class="usa-link" href="#links">add links</a></li>
<li><a class="usa-link" href="#personalised-content">personalize your content</a></li>
<li><a class="usa-link" href="#optional-content">add optional content</a></li>
<li>Choose your messages thoughtfully. Text messages are best to remind/nudge someone to take a specific action or
communicate information at a particular time rather than pushing out broad or overly general information.</li>
<li>Clearly state the issue and expected response. Tell your recipient what you expect from them.</li>
<li>Say only one important thing per message.</li>
<li>Frame the message to encourage action and explain the consequences of not completing the desired action.</li>
</ul>
<h3 class="font-body-lg" id="formatting">Format your content</h3>
<p>You can see a list of formatting instructions on the edit template page:</p>
<ol class="list list-number">
<li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li>
<li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li>
<h3>To create and format your message</h3>
<ol class="list">
<li>All messages start from a template</li>
<li>Click "<a href={{ url_for('.choose_template', service_id=current_service.id) }}>Send Messages</a>". You'll see existing templates.</li>
<li>Add a new template or choose an existing template and select Edit.</li>
</ol>
<h3 class="font-body-lg" id="links">Add links</h3>
<p>When composing a text message, write URLs in full and Notify will convert them into links for you.
</p>
<p>You cannot convert text into a link.
<!-- Research shows that people like to check a URL looks genuine before clicking the link in an email. This is hard to do if the URL is hidden behind clickable link text.-->
</p>
<p>We do not recommend using a third-party link shortening service because:</p>
{# Add links #}
<h2 class="padding-top-1" id="add-links">Add links</h2>
<p>When composing a text message, links to websites or online applications can help your recipient respond quickly.</p>
<ul class="list list-bullet">
<li>your users cannot see where the link will take them</li>
<li>your link might stop working if theres a service outage</li>
<li>you can no longer control where the redirect goes</li>
<li>Write URLs in full and Notify will convert them into links for you. Note that you cannot hyperlink text in Notify
messages.</li>
<li>For link click tracking, you can consider adding campaign parameters to URLs.</li>
<li>All links should point to a government domain.</li>
<li>Link directly to where your recipient needs to take action, not to more information.</li>
</ul>
<h3 class="font-body-lg" id="personalised-content">Personalize your content</h3>
<h3>About link-shortening services</h3>
<p>We do not recommend using a third-party link-shortening service because:</p>
<ul class="list list-bullet">
<li>Your recipient cannot see where the link will take them, which could make them suspect the link is spam/scam.</li>
<li>Your link might stop working if theres a service outage.</li>
<li>You can no longer control where the redirect goes.</li>
</ul>
<p>To personalize the content of your messages, add a placeholder to the template.</p>
{# Personalize content #}
<h2 class="padding-top-1" id="personalize-content">Personalize your content</h2>
<p>Personalizing your content can increase response rates and help the recipient know the text is legitimate.</p>
<ul class="list list-bullet">
<li>Including a person's first name increases response rates.</li>
<li>Specific details such as time and location of an appointment or where suspected fraud use occurred encourages action.</li>
</ul>
<p>Placeholders are filled in with details, like a name or reference number, each time you send a
message.</p>
<p>To add a placeholder to the template:</p>
<ol class="list list-number">
<li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li>
<li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li>
<li>Add a placeholder using double brackets. For example: Hello ((first&nbsp;name)), your reference is
((ref&nbsp;number)).</li>
<li>Select <b class="bold">Save</b>.</li>
<h3>To personalize your content</h3>
<ol class="list">
<li>Add a placeholder to your content by placing two brackets around the personalized elements.</li>
<li>You can manually enter the personalized content or you can upload a spreadsheet with the details and let Notify do the
work for you. See <a href="#prepare-data">data preparation</a>.</li>
</ol>
<p>When you send a message you can either:</p>
<h4>Example</h4>
<p>To personalize with the recipient's first name and include a reference number:</p>
<p class="padding-2 bg-base-lightest">State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 555-123-1234 to make an appointment.</p>
<ul class="list list-bullet">
<li>manually fill in the placeholders yourself</li>
<li>upload a list of personal details and let Notify do it for you</li>
</ul>
<p>Note that variations in the length of personalized content can impact the length of specific messages, and may affect
the number of parts used.</p>
<p>If you upload a list, the column names need to match the placeholders in your template.</p>
{# Add conditional content #}
<h2 class="padding-top-1" id="conditional-content">Add conditional content</h2>
<p>Conditional (or optional) content appears only when a recipient meets certain criteria. This feature allows you to make
all or part of the message contingent upon specific criteria associated with the recipient.</p>
<h3 class="font-body-lg" id="optional-content">Add optional content</h3>
<p>To add optional content to your messages:</p>
<ol class="list list-number">
<li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li>
<li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li>
<li>Use double brackets and ?? to define optional content. For example, if you only want to show something to people
who are under 18: ((under18??Please get your application signed by a parent or guardian.))</li>
<li>Select <b class="bold">Save</b>.</li>
<h3>To add conditional content</h3>
<ol class="list">
<li>Use two brackets and ?? to define the conditional content.</li>
<li>You can manually enter the conditional content or you can upload a spreadsheet with the personal details and let Notify
do the work for you. See <a href="#prepare-data">data preparation</a>.</li>
</ol>
<p>For each person you send this message to, specify yes or no to show or hide this content. You
can either:</p>
<h4>Examples</h4>
<ol class="list">
<li>If you only want to show something to people who are under 18:
</br>
<p class="padding-2 bg-base-lightest">State SNAP: Renewal applications are due by March 15. ((under18??Please get your application signed by a parent or
guardian.))</p>
</li>
<li>
If you want to make people who are homebound aware of the option of virtual visits (but not other message recipients):
</br>
<p class="padding-2 bg-base-lightest">State Medicaid: Please call 555-123-1234 to schedule an appointment. ((homebound??Virtual visits are available.))</p>
</li>
<li>
If you want to send a messages in different languages to different recipients:
</br>
<p class="padding-2 bg-base-lightest">((English??Weve identified unauthorized use on your EBT account. Call the phone number on the back of your card to
cancel or go to your local CSO for immediate replacement.))((Spanish??Hemos identificado un uso no autorizado en su
cuenta EBT. Llame al número de teléfono que aparece en el reverso de su tarjeta para cancelarla o diríjase a su CSO
local para que se la sustituyan inmediatamente.))</p>
</li>
</ol>
<ul class="list list-bullet">
<li>do this yourself</li>
<li>upload a list of personal details and let Notify do it for you</li>
{# Identify your program #}
<h2 class="padding-top-1" id="indentify-program">Identify your program</h2>
<p>You can help your recipients identify your texts as legitimate by customizing your messages to clearly state who they
are from. Consider using the program or benefit name that is most familiar to your recipients.</p>
<h3>To customize your program name</h3>
<p>To change the text message sender from the default service name:</p>
<ol class="list">
<li>Go to the <a href="{{ url_for('main.service_settings', service_id=current_service.id) }}">Settings page</a></li>
<li>Select “Start text messages with service name.”</li>
<li>Change the service name to a familiar program or benefit.</li>
</ol>
{# Prepare your data #}
<h2 class="padding-top-1" id="prepare-data">Prepare your data</h2>
<p>The easiest and most efficient way to personalize your content is by uploading a spreadsheet. Notify can accommodate
many file formats and structures.</p>
<h3>File format</h3>
<p>Notify can accept files in the following formats: CSV, TSV, ODS, and Microsoft Excel.</p>
<h3>File structure</h3>
<ul class="list">
<li>The phone number must be in the first column (Column A) and must be labeled <strong>Phone number</strong>.</li>
<li>Each column must have a unique name.</li>
<li>If you are using Excel, you must either disable the”auto-date/time format” for time and date columns or convert the file
to a CSV prior to loading. (If you do not, Excel will display date/time data in a confusing format.)</li>
</ul>
<p>If you upload a list, the column names need to match the optional content in your template.</p>
<h3>Formatting personalized content</h3>
<p>If you are sending a message with personalized content, such as the first name of the recipient or the appointment time
and location, the names of the column headings have to match the indicator included in the message template.</p>
<p>For example, if the personalized content is the first name of the recipient, and we are using the spreadsheet below, the
indicator in the message needs to be ((First name)), not ((firstname)) or ((name)).</p>
<h2 class="font-body-lg" id="customization">Message customization</h2>
<h3>Formatting conditional content</h3>
<p>If you are sending messages with conditional content, such as content based on the recipients preferred language or
location, the flag to receive the content needs to be captured in its own column with a Yes or No (Y/N) flag.</p>
<h3 class="font-body-lg">Change the text message sender</h3>
<h3>Example</h3>
<table class="usa-table">
<caption class="usa-sr-only">
Example
</caption>
<thead>
<tr>
<th scope="col">Phone number</th>
<th scope="col">First name</th>
<th scope="col">Last name</th>
<th scope="col">Spanish</th>
<th scope="col">English</th>
<th scope="col">Date</th>
<th scope="col">Time</th>
<th scope="col">Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>123-456-7890</td>
<td>Lulu</td>
<td>Praether</td>
<td>N</td>
<td>Y</td>
<td>November 2, 2023</td>
<td>3:25</td>
<td>123 Ford Rd.</td>
</tr>
<tr>
<td>234-567-8901</td>
<td>Sela</td>
<td>Appel</td>
<td>Y</td>
<td>N</td>
<td>November 2, 2023</td>
<td>4:00</td>
<td>123 Ford Rd.</td>
</tr>
<tr>
<td>123-456-7890</td>
<td>Dexter</td>
<td>Moseley</td>
<td>N</td>
<td>Y</td>
<td>November 2, 2023</td>
<td>2:00</td>
<td>123 Ford Rd.</td>
</tr>
</tbody>
</table>
<p>The text message sender tells your users who the message is from.</p>
{# Preventing fraud #}
<h2 class="padding-top-1" id="prevent-fraud">Preventing fraud</h2>
<p>Texting fraud is ever prevalent and while we cant eliminate the risk, we can reduce the chances that recipients will
fall victim to fraud.</p>
<ol class="list">
<li>Never send unnecessary or protected private information.</li>
<li>Remind your recipients that text messaging is not a secure means of communication and they should not send you private
information via text.</li>
<li>Only include links to websites and online applications that are secure.</li>
<li>Send an introductory text letting recipients know you will be texting them and to save the number in their phone.</li>
<li>Include an auto-response with the name of your organization and a contact phone number.</li>
</ol>
<p>To change the text message sender from the default of Notify.gov:</p>
<ol class="list list-number">
<li>Go to the <b class="bold">Text message settings</b> section of the {{
service_link(current_service, 'main.service_settings', 'settings') }} page.</li>
<li>Select <b class="bold">Manage</b> on the <b class="bold">Text message
senders</b> row.</li>
<li>Select <b class="bold">Change</b> or <b class="bold">Add text message
sender</b>.</li>
<h3>Examples</h3>
<ol class="list">
<li>Introductory text:
</br>
<p class="padding-2 bg-base-lightest">State Transit Dept: We're piloting a new way to get important reminders to our staff. Save this number to your phone,
you'll receive updates from us here.</p>
</li>
<li>Auto-response text:
</br>
<p class="padding-2 bg-base-lightest">State Agency: This number is unmonitored. To contact us, call us at 555-123-1234. We will never ask for personal details
in a text. If you have questions about how to protect your privacy, see statename.gov/privacy.</p>
</li>
</ol>
{% endblock %}

View File

@@ -5,26 +5,13 @@
{% from "components/components/back-link/macro.njk" import usaBackLink %}
{% block service_page_title %}
{{ job.original_file_name }}
{{ "Message status" }}
{% endblock %}
{% block maincolumn_content %}
{{ page_header(job.original_file_name) }}
{% if not job.processing_finished %}
<div
data-module="update-content"
data-resource="{{ updates_url }}"
data-key="status"
data-form=""
>
{% endif %}
{{ partials['status']|safe }}
{% if not job.processing_finished %}
</div>
{% endif %}
{{ page_header("Message status") }}
{{ partials['status']|safe }}
{% if not finished %}
<div
data-module="update-content"
@@ -38,6 +25,9 @@
</div>
{% endif %}
<p class="notification-status">
Messages will remain in pending state until carrier status is received, typically 5 minutes.
</p>
{% if not job.processing_finished %}
<div
data-module="update-content"

View File

@@ -10,8 +10,8 @@
<h1 class="font-body-2xl margin-bottom-3">Delivery status</h1>
<p>Notifys real-time dashboard lets you check the status of any message.</p>
<p>For <a class="usa-link" href="{{ url_for("main.security") }}">security</a>, this information is only available for seven days after a message has been sent. You can download a report, including a list of sent messages, for your own records.</p>
<p>This page describes the statuses youll see when youre signed in to Notify.</p>
<p>For <a class="usa-link" href="{{ url_for('main.security') }}">security</a>, this information is only available for seven days after a message has been sent. You can download a report, including a list of sent messages, for your own records.</p>
<p>This page describes the statuses you'll see when you're signed in to Notify.</p>
<!-- <p>If youre using the Notify API, read our <a class="usa-link" href="{{ url_for('.documentation') }}">documentation</a> for a list of API statuses.<p>
@@ -53,13 +53,13 @@
caption_visible=False
) %}
{% for message_status, description in [
('Total', 'The total number of messages that have been sent during the last seven days.'),
('Pending', 'Notify has sent the message to the provider. The provider will try to deliver the message to the recipient for up to 72 hours. Notify is waiting for delivery information.'),
('Sent', 'The mobile networks may not provide any more delivery information.'),
('Delivered', 'The message was successfully delivered. Notify cannot tell you if a user has opened or read a message.'),
('Not delivered', ('The provider could not deliver the message. This can happen if the phone number was wrong or if the network operator rejects the message. If youre sure that these phone numbers are correct, you should <a class="usa-link" href="' + url_for(".support") + '">contact us</a>. If not, you should remove them from your database. Youll still be charged for text messages that cannot be delivered.')|safe),
('Phone not accepting messages right now', 'The provider could not deliver the message. This can happen when the recipients phone is off, has no signal, or their text message inbox is full. You can try to send the message again. Youll still be charged for text messages to phones that are not accepting messages.'),
('Technical failure', 'Your message was not sent because there was a problem between Notify and the provider. Youll have to try sending your messages again. You will not be charged for text messages that are affected by a technical failure.'),
] %}
('Failed', 'The provider could not deliver the message. This can happen if the phone number was wrong or if the network operator
rejects the message. If youre sure that these phone numbers are correct, you should <a class="usa-link" href="/support">contact us</a>. If not, you should remove them from your database. Youll still be charged for text messages that
cannot be delivered.' | safe),
] %}
{% call row() %}
{{ text_field(message_status) }}
{{ text_field(description) }}

View File

@@ -5,7 +5,7 @@
{% from "components/components/button/macro.njk" import usaButton %}
{% block service_page_title %}
{{ "Error" if error else "Preview of {}".format(template.name) }}
{{ "Error" if error else "Select delivery time" }}
{% endblock %}
{% block backLink %}
@@ -40,21 +40,32 @@
{% endcall %}
</div>
{% else %}
{{ page_header('Preview of {}'.format(template.name)) }}
{{ page_header('Select delivery time') }}
{% endif %}
{{ template|string }}
<div class="js-stick-at-bottom-when-scrolling">
<form method="post" enctype="multipart/form-data" action="{{url_for(
'main.send_notification',
'main.preview_notification',
service_id=current_service.id,
template_id=template.id,
help='3' if help else 0
template_id=template.id
)}}" class='page-footer'>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
{% if not error %}
{% set button_text %}Send 1 {{ 1|message_count_label(template.template_type, suffix='') }}{% endset %}
{% if choose_time_form %}
{{ choose_time_form.scheduled_for(param_extensions={
'formGroup': {'classes': 'bottom-gutter-2-3'},
'attributes': {
'data-module': 'radio-select',
'data-categories': choose_time_form.scheduled_for.categories|join(','),
'data-show-now-as-default': 'true'
}
}) }}
{% endif %}
{% set button_text %}
Preview
{% endset %}
{{ usaButton({ "text": button_text }) }}
{% endif %}
</form>

View File

@@ -0,0 +1,74 @@
{% extends "withnav_template.html" %}
{% from "components/banner.html" import banner_wrapper %}
{% from "components/page-header.html" import page_header %}
{% from "components/components/back-link/macro.njk" import usaBackLink %}
{% from "components/components/button/macro.njk" import usaButton %}
{% block service_page_title %}
{{ "Error" if error else "Preview" }}
{% endblock %}
{% block backLink %}
{{ usaBackLink({ "href": back_link_from_preview }) }}
{% endblock %}
{% block maincolumn_content %}
{% if error == 'not-allowed-to-send-to' %}
<div class="bottom-gutter">
{% call banner_wrapper(type='dangerous') %}
{% with
count_of_recipients=1,
template_type_label=(
'phone number' if template.template_type == 'sms' else 'email address'
)
%}
{% include "partials/check/not-allowed-to-send-to.html" %}
{% endwith %}
{% endcall %}
</div>
{% elif error == 'too-many-messages' %}
<div class="bottom-gutter">
{% call banner_wrapper(type='dangerous') %}
{% include "partials/check/too-many-messages.html" %}
{% endcall %}
</div>
{% elif error == 'message-too-long' %}
{# the only row_errors we can get when sending one off messages is that the message is too long #}
<div class="bottom-gutter">
{% call banner_wrapper(type='dangerous') %}
{% include "partials/check/message-too-long.html" %}
{% endcall %}
</div>
{% else %}
{{ page_header('Preview') }}
{% endif %}
<div>
<p class="sms-message-scheduler">Scheduled: {{ scheduled_for |format_datetime_normal if scheduled_for else 'Now'}}</p>
<p class="sms-message-template">Template: {{template.name}}</p>
<p class="sms-message-sender" >From: {{ template.sender }}</p>
<p class="sms-message-sender" >To: {{ recipient }}</p>
</div>
<h2 id="{{ file_contents_header_id }}">Message</h2>
<div class="preview-message"> {{ template|string }}</div>
<div class="js-stick-at-bottom-when-scrolling">
<form method="post" enctype="multipart/form-data" action="{{url_for(
'main.send_notification',
service_id=current_service.id,
template_id=template.id,
help='3' if help else 0
)}}" class='page-footer'>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<!-- <p>Placeholder: This message will be delivered to <b>400 phone numbers</b> and will use a total of <b>800 message parts</b>, leaving Washington DSHS with <b>249,200 message parts remaining</b>.</p> -->
<h3>Does everything look good?</h3>
{% if not error %}
{% set button_text %}
{{ "Schedule" if scheduled_for else 'Send'}}
{% endset %}
{{ usaButton({ "text": button_text }) }}
{% endif %}
</form>
</div>
{% endblock %}

View File

@@ -44,31 +44,33 @@
</div>
</div>
<div class="dashboard-table">
{% call(item, row_number) list_table(
notifications_by_type|reverse,
caption='Messages sent since May 2023',
caption_visible=False,
field_headings=[
'Date',
99|message_count_noun('email')|capitalize,
99|message_count_noun('sms')|capitalize,
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.date | format_date_normal }}
<div class="table-wrapper">
<div class="dashboard-table">
{% call(item, row_number) list_table(
notifications_by_type|reverse,
caption='Messages sent since May 2023',
caption_visible=False,
field_headings=[
'Date',
99|message_count_noun('email')|capitalize,
99|message_count_noun('sms')|capitalize,
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.date | format_date_normal }}
{% endcall %}
{% call field() %}
{{ item.emails|format_thousands }}
{% endcall %}
{% call field() %}
{{ item.sms|format_thousands }}
{% endcall %}
{% endcall %}
{% call field() %}
{{ item.emails|format_thousands }}
{% endcall %}
{% call field() %}
{{ item.sms|format_thousands }}
{% endcall %}
{% endcall %}
<p class="table-show-more-link">
Only showing the last {{ notifications_by_type|length }} days
</p>
<p class="table-show-more-link">
Only showing the last {{ notifications_by_type|length }} days
</p>
</div>
</div>
<h2 class="govuk-heading-m">
@@ -82,26 +84,28 @@
) }}
</div>
</div>
<div class="dashboard-table">
{% call(item, row_number) list_table(
processing_time | reverse,
caption='Messages sent within 10 seconds',
caption_visible=False,
field_headings=[
'Date', 'Percentage'
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.date | format_date_normal }}
<div class="table-wrapper">
<div class="dashboard-table">
{% call(item, row_number) list_table(
processing_time | reverse,
caption='Messages sent within 10 seconds',
caption_visible=False,
field_headings=[
'Date', 'Percentage'
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.date | format_date_normal }}
{% endcall %}
{% call field() %}
{{ '{:.2f}%'.format(item.percentage_under_10_seconds) }}
{% endcall %}
{% endcall %}
{% call field() %}
{{ '{:.2f}%'.format(item.percentage_under_10_seconds) }}
{% endcall %}
{% endcall %}
<p class="table-show-more-link">
Only showing the last {{ processing_time|length }} days
</p>
<p class="table-show-more-link">
Only showing the last {{ processing_time|length }} days
</p>
</div>
</div>
<h2 class="govuk-heading-m">
@@ -120,23 +124,25 @@
<span class="usa-sr-only">using Notify.</span>
</div>
</div>
<div class="dashboard-table">
{% call(item, row_number) list_table(
organizations_using_notify,
caption='Organizations using Notify',
caption_visible=False,
field_headings=[
'Organization', 'Number of live services'
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.organization_name }}
<div class="table-wrapper">
<div class="dashboard-table">
{% call(item, row_number) list_table(
organizations_using_notify,
caption='Organizations using Notify',
caption_visible=False,
field_headings=[
'Organization', 'Number of live services'
],
empty_message='No data to show'
) %}
{% call field() %}
{{ item.organization_name }}
{% endcall %}
{% call field() %}
{{ item.count_of_live_services }}
{% endcall %}
{% endcall %}
{% call field() %}
{{ item.count_of_live_services }}
{% endcall %}
{% endcall %}
</div>
</div>
{% endblock %}

View File

@@ -29,7 +29,7 @@
{{ text_field(item.complaint_type) }}
{{ text_field(item.complaint_date|format_datetime_short if item.complaint_date else None) }}
{{ text_field(item.complaint_date|format_datetime_table if item.complaint_date else None) }}
{% endcall %}

Some files were not shown because too many files have changed in this diff Show More