From 73e3fff1e6a8a540fb293411a6e6f59e7854b3d8 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 11:00:00 -0400 Subject: [PATCH 01/53] Add download actions --- tdrs-frontend/src/actions/reports.js | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tdrs-frontend/src/actions/reports.js b/tdrs-frontend/src/actions/reports.js index 973fb31b3..2687414ca 100644 --- a/tdrs-frontend/src/actions/reports.js +++ b/tdrs-frontend/src/actions/reports.js @@ -1,11 +1,64 @@ +import axios from 'axios' + export const SET_FILE = 'SET_FILE' export const CLEAR_FILE = 'CLEAR_FILE' export const SET_FILE_ERROR = 'SET_FILE_ERROR' export const CLEAR_ERROR = 'CLEAR_ERROR' +export const START_FILE_DOWNLOAD = 'START_FILE_DOWNLOAD' +export const END_FILE_DOWNLOAD = 'END_FILE_DOWNLOAD' +export const FILE_DOWNLOAD_ERROR = 'FILE_DOWNLOAD_ERROR' + +export const FETCH_FILE_LIST = 'FETCH_FILE_LIST' +export const SET_FILE_LIST = 'SET_FILE_LIST' + export const clearError = ({ section }) => (dispatch) => { dispatch({ type: CLEAR_ERROR, payload: { section } }) } +/** + Get a list of files that can be downloaded, mainly used to decide if the download button should be present. +*/ +export const getAvailableFileList = ({ year, quarter = 'Q1' }) => async ( + dispatch +) => { + const response = await axios({ + url: `/mock/reports/${year}/${quarter}`, + method: 'get', + responseType: 'json', + }) +} + +export const download = ({ year, quarter = 'Q1', section }) => async ( + dispatch +) => { + try { + dispatch({ type: START_FILE_DOWNLOAD }) + + const response = await axios({ + url: `/mock/reports/data-files/${year}/${quarter}/${section}`, + method: 'get', + responseType: 'blob', + }) + const { data } = response + + dispatch({ + type: END_FILE_DOWNLOAD, + payload: { + year, + quarter, + section, + data, + }, + }) + } catch (error) { + dispatch({ + type: FILE_DOWNLOAD_ERROR, + payload: { error, year, quarter, section }, + }) + return false + } + return true +} // Main Redux action to add files to the state export const upload = ({ file, section }) => async (dispatch) => { From 2b297d35e97507749fd0c0e5e99732f7bbb60b8a Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 11:59:12 -0400 Subject: [PATCH 02/53] Possible change comment --- tdrs-frontend/src/actions/sttList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tdrs-frontend/src/actions/sttList.js b/tdrs-frontend/src/actions/sttList.js index 6c162cf1a..e8aef1ba3 100644 --- a/tdrs-frontend/src/actions/sttList.js +++ b/tdrs-frontend/src/actions/sttList.js @@ -38,6 +38,7 @@ export const fetchSttList = () => async (dispatch) => { }) if (data) { + // shouldn't this logic be done by the backend serializer? data.forEach((item, i) => { if (item.name === 'Federal Government') { data.splice(i, 1) From f2b86d42d05d30824ffbcddc4c985658222feeb4 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 12:00:34 -0400 Subject: [PATCH 03/53] Add download button --- .../src/components/FileUpload/FileUpload.jsx | 63 +++++++++++++++---- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/tdrs-frontend/src/components/FileUpload/FileUpload.jsx b/tdrs-frontend/src/components/FileUpload/FileUpload.jsx index 73e760d62..ba3067f48 100644 --- a/tdrs-frontend/src/components/FileUpload/FileUpload.jsx +++ b/tdrs-frontend/src/components/FileUpload/FileUpload.jsx @@ -1,23 +1,54 @@ -import React from 'react' +import React, { useEffect } from 'react' import PropTypes from 'prop-types' import { useDispatch, useSelector } from 'react-redux' -import { clearError, upload } from '../../actions/reports' +import axios from 'axios' + +import { clearError, upload, download } from '../../actions/reports' + +import Button from '../Button' + +// helpers +const getReports = (state) => state.reports +const toLower = (s) => s.toLowerCase() + +const initiateDownloadSequence = ({ + data, + year, + quarter, + section, + canDownload, +}) => () => { + if (canDownload) { + const url = window.URL.createObjectURL(new Blob([data])) + const link = document.createElement('a') + + link.href = url + link.setAttribute('download', `${year}.${quarter}.${section}.txt`) + + document.body.appendChild(link) + + link.click() + + document.body.removeChild(link) + } +} function FileUpload({ section }) { // e.g. 'Aggregate Case Data' => 'aggregate-case-data' // The set of uploaded files in our Redux state - const files = useSelector((state) => state.reports.files) + const { files, year, quarter, data, canDownload } = useSelector(getReports) const dispatch = useDispatch() + useEffect(initiateDownloadSequence({ year, quarter, data, canDownload }), [ + data, + ]) + // e.g. "1 - Active Case Data" => ["1", "Active Case Data"] const [sectionNumber, sectionName] = section.split(' - ') const file = files.find((currentFile) => sectionName === currentFile.section) - const formattedSectionName = file.section - .split(' ') - .map((word) => word.toLowerCase()) - .join('-') + const formattedSectionName = file.section.split(' ').map(toLower).join('-') const fileName = file?.fileName const hasUploadedFile = Boolean(fileName) @@ -26,14 +57,13 @@ function FileUpload({ section }) { ? `Selected File ${file?.fileName}. To change the selected file, click this button.` : `Drag file here or choose from folder.` + const downloadFile = ({ target }) => { + dispatch(clearError({ section })) + dispatch(download({ section, year })) + } const uploadFile = ({ target }) => { dispatch(clearError({ section: target.name })) - dispatch( - upload({ - file: target.files[0], - section: target.name, - }) - ) + dispatch(upload({ file: target.files[0], section: target.name })) } return ( @@ -72,6 +102,13 @@ function FileUpload({ section }) { accept=".txt" data-errormessage="We can’t process that file format. Please provide a .txt file." /> +
+ {canDownload ? ( + + ) : null} +
) } From d96f7ccd1a56a1f512fa5968fd70a669ad5e2007 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 12:03:15 -0400 Subject: [PATCH 04/53] Add hooks to get list of available files --- .../src/components/UploadReport/UploadReport.jsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tdrs-frontend/src/components/UploadReport/UploadReport.jsx b/tdrs-frontend/src/components/UploadReport/UploadReport.jsx index 6b2889fd8..930a1e7cb 100644 --- a/tdrs-frontend/src/components/UploadReport/UploadReport.jsx +++ b/tdrs-frontend/src/components/UploadReport/UploadReport.jsx @@ -1,7 +1,8 @@ import React, { useEffect, useRef } from 'react' -import { useSelector } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import PropTypes from 'prop-types' import { fileInput } from 'uswds/src/js/components' +import { getAvailableFileList } from '../../actions/reports' import Button from '../Button' @@ -13,11 +14,18 @@ function UploadReport({ handleCancel }) { // Ensure newly rendered header is focused, else it won't be read be screen readers. const headerRef = useRef(null) + const dispatch = useDispatch() useEffect(() => { headerRef.current.focus() }, []) + useEffect(() => dispatch(getAvailableFileList({ selectedYear })), [ + dispatch, + getAvailableFileList, + selectedYear, + ]) + useEffect(() => { // `init` for the uswds fileInput must be called on the // initial render for it to load properly From e0a295473146446e1713bbb86bd6e568911610f4 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 12:03:36 -0400 Subject: [PATCH 05/53] Add initial test --- .../UploadReport/UploadReport.test.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tdrs-frontend/src/components/UploadReport/UploadReport.test.js b/tdrs-frontend/src/components/UploadReport/UploadReport.test.js index 1cc762a48..c2573c59b 100644 --- a/tdrs-frontend/src/components/UploadReport/UploadReport.test.js +++ b/tdrs-frontend/src/components/UploadReport/UploadReport.test.js @@ -73,6 +73,31 @@ describe('UploadReport', () => { expect(store.dispatch).toHaveBeenCalledTimes(2) }) + it('should display a download button when the file is available for download.', () => { + const store = mockStore(initialState) + const origDispatch = store.dispatch + store.dispatch = jest.fn(origDispatch) + + const { getByLabelText } = render( + + + + ) + + const fileInputs = getByLabelText('Section 1 - Active Case Data') + + const newFile = new File(['test'], 'test.txt', { type: 'text/plain' }) + + const buttons = container.querySelectorAll('.tanf-file-download-btn') + + fireEvent.change(fileInput, { + target: { + files: [newFile], + }, + }) + + expect(store.dispatch).toHaveBeenCalledTimes(2) + }) it('should render a div with class "usa-form-group--error" if there is an error', () => { // Recreate the store with the intial state, except add an `error` object to one of the files. From 535c0f42ec5e66a0cf1cb7e95c9d1f883fe8bd45 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Fri, 16 Apr 2021 12:14:19 -0400 Subject: [PATCH 06/53] add mirage --- tdrs-frontend/package.json | 1 + tdrs-frontend/src/index.js | 2 ++ tdrs-frontend/src/mirage.js | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 tdrs-frontend/src/mirage.js diff --git a/tdrs-frontend/package.json b/tdrs-frontend/package.json index 0a04cc332..92e599bc4 100644 --- a/tdrs-frontend/package.json +++ b/tdrs-frontend/package.json @@ -12,6 +12,7 @@ "history": "^4.7.2", "immutable": "^4.0.0-rc.12", "include-media": "^1.4.9", + "miragejs": "^0.1.41", "prop-types": "^15.7.2", "react": "^16.14.0", "react-dom": "^16.14.0", diff --git a/tdrs-frontend/src/index.js b/tdrs-frontend/src/index.js index 577b9c93b..2e88972ad 100644 --- a/tdrs-frontend/src/index.js +++ b/tdrs-frontend/src/index.js @@ -11,6 +11,7 @@ import App from './App' import 'uswds/dist/js/uswds' import './index.scss' +import startMirage from './mirage' axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = 'X-CSRFToken' @@ -18,6 +19,7 @@ axios.defaults.withCredentials = true const store = configureStore() store.dispatch(fetchAuth()) +startMirage() ReactDOM.render( diff --git a/tdrs-frontend/src/mirage.js b/tdrs-frontend/src/mirage.js new file mode 100644 index 000000000..09f7d8076 --- /dev/null +++ b/tdrs-frontend/src/mirage.js @@ -0,0 +1,24 @@ +import { createServer } from 'miragejs' + +export default function startMirage( + { environment } = { environment: 'development' } +) { + return createServer({ + environment, + + routes() { + this.namespace = 'mock_api' + + this.post('/reports/', () => { + return 'Success' + }) + this.get('/reports/data-files/:year/:quarter/:section', () => { + return 'some text' + }) + + // Allow unhandled requests to pass through + this.passthrough(`${process.env.REACT_APP_BACKEND_URL}/**`) + this.passthrough(`${process.env.REACT_APP_BACKEND_HOST}/**`) + }, + }) +} From f4c25de3e608cdbb3da572029bd9ff037add0612 Mon Sep 17 00:00:00 2001 From: Aaron Beavers Date: Thu, 22 Apr 2021 10:53:16 -0400 Subject: [PATCH 07/53] Auto stash before merge of "epics/89/issues/416/download-files-frontend" and "origin/raft-tdp-main" --- scripts/.#set-backend-env-vars.sh | 1 + tdrs-frontend/src/actions/reports.js | 46 ++++- tdrs-frontend/src/assets/App.scss | 4 +- tdrs-frontend/src/assets/Button.scss | 2 +- tdrs-frontend/src/assets/EditProfile.scss | 4 +- tdrs-frontend/src/assets/FileUpload.scss | 4 +- tdrs-frontend/src/assets/Footer.scss | 4 +- tdrs-frontend/src/assets/GovBanner.scss | 8 +- tdrs-frontend/src/assets/Header.scss | 7 +- tdrs-frontend/src/assets/IdleTimer.scss | 28 +-- .../src/assets/uswds/_uswds-theme-color.scss | 186 +++++++++--------- .../assets/uswds/_uswds-theme-components.scss | 68 +++---- .../assets/uswds/_uswds-theme-general.scss | 12 +- .../assets/uswds/_uswds-theme-spacing.scss | 6 +- .../assets/uswds/_uswds-theme-typography.scss | 52 ++--- .../assets/uswds/_uswds-theme-utilities.scss | 120 +++++------ .../src/components/FileUpload/FileUpload.jsx | 133 ++++++++++--- .../src/components/Reports/Reports.jsx | 2 +- .../components/UploadReport/UploadReport.jsx | 20 +- .../UploadReport/UploadReport.test.js | 12 +- tdrs-frontend/src/index.scss | 14 +- tdrs-frontend/src/mirage.js | 12 ++ tdrs-frontend/src/reducers/reports.js | 26 +++ tdrs-frontend/src/serviceWorker.js | 70 +++---- tdrs-frontend/src/theme/_global.scss | 7 +- 25 files changed, 507 insertions(+), 341 deletions(-) create mode 120000 scripts/.#set-backend-env-vars.sh diff --git a/scripts/.#set-backend-env-vars.sh b/scripts/.#set-backend-env-vars.sh new file mode 120000 index 000000000..4c2256b07 --- /dev/null +++ b/scripts/.#set-backend-env-vars.sh @@ -0,0 +1 @@ +aaronb@prometheus.66582:1617035669 \ No newline at end of file diff --git a/tdrs-frontend/src/actions/reports.js b/tdrs-frontend/src/actions/reports.js index 096e62b3e..1b897c85c 100644 --- a/tdrs-frontend/src/actions/reports.js +++ b/tdrs-frontend/src/actions/reports.js @@ -12,6 +12,8 @@ export const FILE_DOWNLOAD_ERROR = 'FILE_DOWNLOAD_ERROR' export const FETCH_FILE_LIST = 'FETCH_FILE_LIST' export const SET_FILE_LIST = 'SET_FILE_LIST' +export const FETCH_FILE_LIST_ERROR = 'FETCH_FILE_LIST_ERROR' +export const DOWNLOAD_DIALOG_OPEN = 'DOWNLOAD_DIALOG_OPEN' export const clearFile = ({ section }) => (dispatch) => { dispatch({ type: CLEAR_FILE, payload: { section } }) @@ -26,11 +28,26 @@ export const clearError = ({ section }) => (dispatch) => { export const getAvailableFileList = ({ year, quarter = 'Q1' }) => async ( dispatch ) => { - const response = await axios({ - url: `/mock/reports/${year}/${quarter}`, - method: 'get', - responseType: 'json', + dispatch({ + type: FETCH_FILE_LIST, }) + try { + const response = await axios({ + url: `/mock_api/reports/${year}/${quarter}`, + method: 'get', + responseType: 'json', + }) + dispatch({ + type: SET_FILE_LIST, + payload: { + data: response.data, + }, + }) + } catch (error) { + dispatch({ + type: FETCH_FILE_LIST_ERROR, + }) + } } export const download = ({ year, quarter = 'Q1', section }) => async ( @@ -40,7 +57,7 @@ export const download = ({ year, quarter = 'Q1', section }) => async ( dispatch({ type: START_FILE_DOWNLOAD }) const response = await axios({ - url: `/mock/reports/data-files/${year}/${quarter}/${section}`, + url: `/mock_api/reports/data-files/${year}/${quarter}/${section}`, method: 'get', responseType: 'blob', }) @@ -49,10 +66,10 @@ export const download = ({ year, quarter = 'Q1', section }) => async ( dispatch({ type: END_FILE_DOWNLOAD, payload: { + data, year, quarter, section, - data, }, }) } catch (error) { @@ -97,3 +114,20 @@ export const setStt = (stt) => (dispatch) => { export const setYear = (year) => (dispatch) => { dispatch({ type: SET_SELECTED_YEAR, payload: { year } }) } + +export const triggerDownloadDialog = ({ year, quarter, section, data }) => ( + dispatch +) => { + const url = window.URL.createObjectURL(new Blob([data])) + const link = document.createElement('a') + + link.href = url + link.setAttribute('download', `${year}.${quarter}.${section}.txt`) + + document.body.appendChild(link) + + link.click() + + document.body.removeChild(link) + dispatch({ type: DOWNLOAD_DIALOG_OPEN }) +} diff --git a/tdrs-frontend/src/assets/App.scss b/tdrs-frontend/src/assets/App.scss index 6da13a10a..0d7b59496 100644 --- a/tdrs-frontend/src/assets/App.scss +++ b/tdrs-frontend/src/assets/App.scss @@ -1,6 +1,8 @@ @import 'theme/_global.scss'; -html, body, div#root { +html, +body, +div#root { height: 100%; min-height: 100%; padding: 0; diff --git a/tdrs-frontend/src/assets/Button.scss b/tdrs-frontend/src/assets/Button.scss index a2a0aae89..e960a40bb 100644 --- a/tdrs-frontend/src/assets/Button.scss +++ b/tdrs-frontend/src/assets/Button.scss @@ -2,4 +2,4 @@ .usa-button:hover { font-size: 1rem; background-color: $primary-medium-blue; -} \ No newline at end of file +} diff --git a/tdrs-frontend/src/assets/EditProfile.scss b/tdrs-frontend/src/assets/EditProfile.scss index 690bf6e18..4f034a410 100644 --- a/tdrs-frontend/src/assets/EditProfile.scss +++ b/tdrs-frontend/src/assets/EditProfile.scss @@ -1,3 +1,3 @@ .usa-combo-box__input--error { - border: .25rem solid #b50909; -} \ No newline at end of file + border: 0.25rem solid #b50909; +} diff --git a/tdrs-frontend/src/assets/FileUpload.scss b/tdrs-frontend/src/assets/FileUpload.scss index 66859dfba..d1079ed8c 100644 --- a/tdrs-frontend/src/assets/FileUpload.scss +++ b/tdrs-frontend/src/assets/FileUpload.scss @@ -1,4 +1,4 @@ // Override the default white background color of the USWDS Inputs .usa-file-input__box { - background: #F0F0F0; -} \ No newline at end of file + background: #f0f0f0; +} diff --git a/tdrs-frontend/src/assets/Footer.scss b/tdrs-frontend/src/assets/Footer.scss index 4e6931090..4e9a6a874 100644 --- a/tdrs-frontend/src/assets/Footer.scss +++ b/tdrs-frontend/src/assets/Footer.scss @@ -4,5 +4,5 @@ } .usa-footer__primary-link { - color: $primary-acf-blue -} \ No newline at end of file + color: $primary-acf-blue; +} diff --git a/tdrs-frontend/src/assets/GovBanner.scss b/tdrs-frontend/src/assets/GovBanner.scss index b2292ae6c..e0e5f2f2a 100644 --- a/tdrs-frontend/src/assets/GovBanner.scss +++ b/tdrs-frontend/src/assets/GovBanner.scss @@ -1,4 +1,4 @@ -@include media(">=medium") { +@include media('>=medium') { .usa-banner { background-color: #ebf3fa; &__header { @@ -21,9 +21,9 @@ } } } - &__button[aria-expanded=true]::after, - &__button[aria-expanded=true]:hover::after { + &__button[aria-expanded='true']::after, + &__button[aria-expanded='true']:hover::after { background-color: white; } } -} \ No newline at end of file +} diff --git a/tdrs-frontend/src/assets/Header.scss b/tdrs-frontend/src/assets/Header.scss index 69fa7ed1e..01da28348 100644 --- a/tdrs-frontend/src/assets/Header.scss +++ b/tdrs-frontend/src/assets/Header.scss @@ -6,7 +6,7 @@ color: $accent-magenta; } -.usa-header--extended .usa-nav__primary-item > .usa-current::after, +.usa-header--extended .usa-nav__primary-item > .usa-current::after, .usa-header--extended .usa-nav__primary-item > .usa-nav__link:hover::after { background-color: $accent-magenta; } @@ -18,7 +18,8 @@ } } -.usa-menu-btn, .usa-menu-btn:hover { +.usa-menu-btn, +.usa-menu-btn:hover { background-color: $primary-medium-blue; } @@ -29,4 +30,4 @@ .usa-nav__primary > .usa-nav__primary-item > .usa-current { font-weight: 700; -} \ No newline at end of file +} diff --git a/tdrs-frontend/src/assets/IdleTimer.scss b/tdrs-frontend/src/assets/IdleTimer.scss index cb28a8df8..c371f183e 100644 --- a/tdrs-frontend/src/assets/IdleTimer.scss +++ b/tdrs-frontend/src/assets/IdleTimer.scss @@ -1,13 +1,13 @@ .modal { - position: fixed; - z-index: 1; + position: fixed; + z-index: 1; left: 0; top: 0; - width: 100%; - height: 100%; + width: 100%; + height: 100%; overflow: auto; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,0.4); + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.4); } /* Modal Content/Box */ @@ -42,13 +42,19 @@ padding: 0; border: 1px solid #888; width: 80%; - box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); animation-name: animatetop; - animation-duration: 0.4s + animation-duration: 0.4s; } /* Add Animation */ @keyframes animatetop { - from {top: -300px; opacity: 0} - to {top: 0; opacity: 1} -} \ No newline at end of file + from { + top: -300px; + opacity: 0; + } + to { + top: 0; + opacity: 1; + } +} diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-color.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-color.scss index 617f47c93..d4c4b7f34 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-color.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-color.scss @@ -17,39 +17,39 @@ https://designsystem.digital.gov/design-tokens/color ---------------------------------------- */ -$disabled-button-color: #4A4A4A; -$gov-banner-background: #122E51; +$disabled-button-color: #4a4a4a; +$gov-banner-background: #122e51; /* Primary Color Palette */ -$primary-pale-blue: #BCD9ED; -$primary-light-pale-blue: #E2EFF7; -$primary-medium-blue: #336A90; -$primary-light-medium-blue: #779CB5; -$primary-acf-blue: #264A64; -$primary-deep-acf-blue: #172C3C; -$primary-neutral: #BFB0A3; -$primary-deep-neutral: #8F847A; +$primary-pale-blue: #bcd9ed; +$primary-light-pale-blue: #e2eff7; +$primary-medium-blue: #336a90; +$primary-light-medium-blue: #779cb5; +$primary-acf-blue: #264a64; +$primary-deep-acf-blue: #172c3c; +$primary-neutral: #bfb0a3; +$primary-deep-neutral: #8f847a; $primary-medium-gray: #475260; -$primary-deep-medium-gray: #323A45; -$primary-light-medium-gray: #80858C; -$primary-ligh-medium-gray-accessible: #72777E; -$primary-light-cool-gray: #DDE2E8; +$primary-deep-medium-gray: #323a45; +$primary-light-medium-gray: #80858c; +$primary-ligh-medium-gray-accessible: #72777e; +$primary-light-cool-gray: #dde2e8; $primary-graphite: #221122; /* Accent Color Palette */ -$accent-teal: #63BAB0; -$accent-light-teal: #A6D8D2; +$accent-teal: #63bab0; +$accent-light-teal: #a6d8d2; $accent-deep-teal: #407972; -$accent-dark-teal: #2D544F; -$accent-yellow: #F9E585; -$accent-light-yellow: #FCF1BF; -$accent-magenta: #A12854; -$accent-medium-deep-magenta: #711C3B; +$accent-dark-teal: #2d544f; +$accent-yellow: #f9e585; +$accent-light-yellow: #fcf1bf; +$accent-magenta: #a12854; +$accent-medium-deep-magenta: #711c3b; $accent-deep-magenta: #481226; -$accent-orange: #E29F4D; -$accent-light-orange: #ECBF88; +$accent-orange: #e29f4d; +$accent-light-orange: #ecbf88; /* ---------------------------------------- @@ -58,56 +58,56 @@ Theme palette colors */ // Base colors -$theme-color-base-family: "gray-cool"; -$theme-color-base-lightest: "gray-5"; -$theme-color-base-lighter: "gray-cool-10"; -$theme-color-base-light: "gray-cool-30"; -$theme-color-base: "gray-cool-50"; -$theme-color-base-dark: "gray-cool-60"; -$theme-color-base-darker: "gray-cool-70"; -$theme-color-base-darkest: "gray-90"; -$theme-color-base-ink: "gray-90"; +$theme-color-base-family: 'gray-cool'; +$theme-color-base-lightest: 'gray-5'; +$theme-color-base-lighter: 'gray-cool-10'; +$theme-color-base-light: 'gray-cool-30'; +$theme-color-base: 'gray-cool-50'; +$theme-color-base-dark: 'gray-cool-60'; +$theme-color-base-darker: 'gray-cool-70'; +$theme-color-base-darkest: 'gray-90'; +$theme-color-base-ink: 'gray-90'; // Primary colors -$theme-color-primary-family: "blue"; +$theme-color-primary-family: 'blue'; $theme-color-primary-lightest: false; -$theme-color-primary-lighter: "blue-10"; -$theme-color-primary-light: "blue-30"; -$theme-color-primary: "blue-60v"; -$theme-color-primary-vivid: "blue-warm-60v"; -$theme-color-primary-dark: "blue-warm-70v"; -$theme-color-primary-darker: "blue-warm-80v"; +$theme-color-primary-lighter: 'blue-10'; +$theme-color-primary-light: 'blue-30'; +$theme-color-primary: 'blue-60v'; +$theme-color-primary-vivid: 'blue-warm-60v'; +$theme-color-primary-dark: 'blue-warm-70v'; +$theme-color-primary-darker: 'blue-warm-80v'; $theme-color-primary-darkest: false; // Secondary colors -$theme-color-secondary-family: "red"; +$theme-color-secondary-family: 'red'; $theme-color-secondary-lightest: false; -$theme-color-secondary-lighter: "red-cool-10"; -$theme-color-secondary-light: "red-30"; -$theme-color-secondary: "red-50"; -$theme-color-secondary-vivid: "red-cool-50v"; -$theme-color-secondary-dark: "red-60v"; -$theme-color-secondary-darker: "red-70v"; +$theme-color-secondary-lighter: 'red-cool-10'; +$theme-color-secondary-light: 'red-30'; +$theme-color-secondary: 'red-50'; +$theme-color-secondary-vivid: 'red-cool-50v'; +$theme-color-secondary-dark: 'red-60v'; +$theme-color-secondary-darker: 'red-70v'; $theme-color-secondary-darkest: false; // Accent warm colors -$theme-color-accent-warm-family: "orange"; +$theme-color-accent-warm-family: 'orange'; $theme-color-accent-warm-lightest: false; -$theme-color-accent-warm-lighter: "orange-10"; -$theme-color-accent-warm-light: "orange-20v"; -$theme-color-accent-warm: "orange-30v"; -$theme-color-accent-warm-dark: "orange-50v"; -$theme-color-accent-warm-darker: "orange-60"; +$theme-color-accent-warm-lighter: 'orange-10'; +$theme-color-accent-warm-light: 'orange-20v'; +$theme-color-accent-warm: 'orange-30v'; +$theme-color-accent-warm-dark: 'orange-50v'; +$theme-color-accent-warm-darker: 'orange-60'; $theme-color-accent-warm-darkest: false; // Accent cool colors -$theme-color-accent-cool-family: "blue-cool"; +$theme-color-accent-cool-family: 'blue-cool'; $theme-color-accent-cool-lightest: false; -$theme-color-accent-cool-lighter: "blue-cool-5v"; -$theme-color-accent-cool-light: "blue-cool-20v"; -$theme-color-accent-cool: "cyan-30v"; -$theme-color-accent-cool-dark: "blue-cool-40v"; -$theme-color-accent-cool-darker: "blue-cool-60v"; +$theme-color-accent-cool-lighter: 'blue-cool-5v'; +$theme-color-accent-cool-light: 'blue-cool-20v'; +$theme-color-accent-cool: 'cyan-30v'; +$theme-color-accent-cool-dark: 'blue-cool-40v'; +$theme-color-accent-cool-darker: 'blue-cool-60v'; $theme-color-accent-cool-darkest: false; /* @@ -117,42 +117,42 @@ State palette colors */ // Error colors -$theme-color-error-family: "red-warm"; -$theme-color-error-lighter: "red-warm-10"; -$theme-color-error-light: "red-warm-30v"; -$theme-color-error: "red-warm-50v"; -$theme-color-error-dark: "red-60v"; -$theme-color-error-darker: "red-70"; +$theme-color-error-family: 'red-warm'; +$theme-color-error-lighter: 'red-warm-10'; +$theme-color-error-light: 'red-warm-30v'; +$theme-color-error: 'red-warm-50v'; +$theme-color-error-dark: 'red-60v'; +$theme-color-error-darker: 'red-70'; // Warning colors -$theme-color-warning-family: "gold"; -$theme-color-warning-lighter: "yellow-5"; -$theme-color-warning-light: "yellow-10v"; -$theme-color-warning: "gold-20v"; -$theme-color-warning-dark: "gold-30v"; -$theme-color-warning-darker: "gold-50v"; +$theme-color-warning-family: 'gold'; +$theme-color-warning-lighter: 'yellow-5'; +$theme-color-warning-light: 'yellow-10v'; +$theme-color-warning: 'gold-20v'; +$theme-color-warning-dark: 'gold-30v'; +$theme-color-warning-darker: 'gold-50v'; // Success colors -$theme-color-success-family: "green-cool"; -$theme-color-success-lighter: "green-cool-5"; -$theme-color-success-light: "green-cool-20v"; -$theme-color-success: "green-cool-40v"; -$theme-color-success-dark: "green-cool-50"; -$theme-color-success-darker: "green-cool-60"; +$theme-color-success-family: 'green-cool'; +$theme-color-success-lighter: 'green-cool-5'; +$theme-color-success-light: 'green-cool-20v'; +$theme-color-success: 'green-cool-40v'; +$theme-color-success-dark: 'green-cool-50'; +$theme-color-success-darker: 'green-cool-60'; // Info colors -$theme-color-info-family: "cyan"; -$theme-color-info-lighter: "cyan-5"; -$theme-color-info-light: "cyan-20"; -$theme-color-info: "cyan-30v"; -$theme-color-info-dark: "cyan-40v"; -$theme-color-info-darker: "blue-cool-60"; +$theme-color-info-family: 'cyan'; +$theme-color-info-lighter: 'cyan-5'; +$theme-color-info-light: 'cyan-20'; +$theme-color-info: 'cyan-30v'; +$theme-color-info-dark: 'cyan-40v'; +$theme-color-info-darker: 'blue-cool-60'; // Disabled colors -$theme-color-disabled-family: "gray"; -$theme-color-disabled-light: "gray-10"; -$theme-color-disabled: "gray-20"; -$theme-color-disabled-dark: "gray-30"; +$theme-color-disabled-family: 'gray'; +$theme-color-disabled-light: 'gray-10'; +$theme-color-disabled: 'gray-20'; +$theme-color-disabled-dark: 'gray-30'; /* ---------------------------------------- @@ -161,10 +161,10 @@ General colors */ // Links -$theme-link-color: "primary"; -$theme-link-visited-color: "violet-70v"; -$theme-link-hover-color: "primary-dark"; -$theme-link-active-color: "primary-darker"; -$theme-link-reverse-color: "base-lighter"; -$theme-link-reverse-hover-color: "base-lightest"; -$theme-link-reverse-active-color: "white"; +$theme-link-color: 'primary'; +$theme-link-visited-color: 'violet-70v'; +$theme-link-hover-color: 'primary-dark'; +$theme-link-active-color: 'primary-darker'; +$theme-link-reverse-color: 'base-lighter'; +$theme-link-reverse-hover-color: 'base-lightest'; +$theme-link-reverse-active-color: 'white'; diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-components.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-components.scss index bb92ab4ba..acfb1bcfa 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-components.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-components.scss @@ -19,86 +19,86 @@ https://designsystem.digital.gov/design-tokens // Accordion $theme-accordion-border-width: 0.5; -$theme-accordion-border-color: "base-lightest"; -$theme-accordion-font-family: "body"; +$theme-accordion-border-color: 'base-lightest'; +$theme-accordion-font-family: 'body'; // Alert $theme-alert-bar-width: 1; -$theme-alert-font-family: "ui"; +$theme-alert-font-family: 'ui'; $theme-alert-icon-size: 4; $theme-alert-padding-x: 2.5; // Banner -$theme-banner-background-color: "base-lightest"; -$theme-banner-font-family: "ui"; +$theme-banner-background-color: 'base-lightest'; +$theme-banner-font-family: 'ui'; $theme-banner-link-color: default; -$theme-banner-max-width: "desktop"; +$theme-banner-max-width: 'desktop'; // Breadcrumb -$theme-breadcrumb-background-color: "white"; -$theme-breadcrumb-font-size: "sm"; -$theme-breadcrumb-font-family: "body"; +$theme-breadcrumb-background-color: 'white'; +$theme-breadcrumb-font-size: 'sm'; +$theme-breadcrumb-font-family: 'body'; $theme-breadcrumb-link-color: default; -$theme-breadcrumb-min-width: "mobile-lg"; +$theme-breadcrumb-min-width: 'mobile-lg'; $theme-breadcrumb-padding-bottom: 2; $theme-breadcrumb-padding-top: 2; $theme-breadcrumb-padding-x: 0; -$theme-breadcrumb-separator-color: "base"; +$theme-breadcrumb-separator-color: 'base'; // Button -$theme-button-font-family: "ui"; -$theme-button-border-radius: "md"; +$theme-button-font-family: 'ui'; +$theme-button-border-radius: 'md'; $theme-button-small-width: 6; $theme-button-stroke-width: 2px; // Card -$theme-card-border-color: "base-lighter"; -$theme-card-border-radius: "lg"; +$theme-card-border-color: 'base-lighter'; +$theme-card-border-radius: 'lg'; $theme-card-border-width: 2px; $theme-card-gap: 2; -$theme-card-flag-min-width: "tablet"; -$theme-card-flag-image-width: "card-lg"; -$theme-card-font-family: "body"; -$theme-card-header-typeset: "heading", "lg", 2; +$theme-card-flag-min-width: 'tablet'; +$theme-card-flag-image-width: 'card-lg'; +$theme-card-font-family: 'body'; +$theme-card-header-typeset: 'heading', 'lg', 2; $theme-card-margin-bottom: 4; $theme-card-padding-perimeter: 3; $theme-card-padding-y: 2; // Footer -$theme-footer-font-family: "body"; -$theme-footer-max-width: "desktop"; +$theme-footer-font-family: 'body'; +$theme-footer-max-width: 'desktop'; // Form and input -$theme-checkbox-border-radius: "sm"; -$theme-form-font-family: "ui"; +$theme-checkbox-border-radius: 'sm'; +$theme-form-font-family: 'ui'; $theme-input-line-height: 3; -$theme-input-max-width: "mobile-lg"; +$theme-input-max-width: 'mobile-lg'; $theme-input-select-border-width: 2px; $theme-input-select-size: 2.5; $theme-input-state-border-width: 0.5; // Header -$theme-header-font-family: "ui"; +$theme-header-font-family: 'ui'; $theme-header-logo-text-width: 33%; -$theme-header-max-width: "desktop"; -$theme-header-min-width: "desktop"; +$theme-header-max-width: 'desktop'; +$theme-header-min-width: 'desktop'; // Hero -$theme-hero-image: "#{$theme-image-path}/hero.png"; +$theme-hero-image: '#{$theme-image-path}/hero.png'; // Navigation -$theme-navigation-font-family: "ui"; +$theme-navigation-font-family: 'ui'; $theme-megamenu-columns: 3; // Search -$theme-search-font-family: "ui"; +$theme-search-font-family: 'ui'; $theme-search-min-width: 27ch; // Sidenav $theme-sidenav-current-border-width: 0.5; -$theme-sidenav-font-family: "ui"; +$theme-sidenav-font-family: 'ui'; // Tooltips -$theme-tooltip-background-color: "ink"; -$theme-tooltip-font-color: "base-lightest"; -$theme-tooltip-font-size: "xs"; +$theme-tooltip-background-color: 'ink'; +$theme-tooltip-font-color: 'base-lightest'; +$theme-tooltip-font-size: 'xs'; diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-general.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-general.scss index e615e1995..5dd575781 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-general.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-general.scss @@ -25,7 +25,7 @@ Relative image file path ---------------------------------------- */ -$theme-image-path: "../../../img"; +$theme-image-path: '../../../img'; /* ---------------------------------------- @@ -48,12 +48,12 @@ Namespace */ $theme-namespace: ( - "grid": ( - namespace: "grid-", + 'grid': ( + namespace: 'grid-', output: true, ), - "utility": ( - namespace: "u-", + 'utility': ( + namespace: 'u-', output: false, ), ); @@ -87,7 +87,7 @@ Focus styles ---------------------------------------- */ -$theme-focus-color: "blue-40v"; +$theme-focus-color: 'blue-40v'; $theme-focus-offset: 0; $theme-focus-style: solid; $theme-focus-width: 0.5; diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-spacing.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-spacing.scss index 3905f8a6a..206185a9f 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-spacing.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-spacing.scss @@ -79,7 +79,7 @@ widescreen ---------------------------------------- */ -$theme-grid-container-max-width: "desktop"; +$theme-grid-container-max-width: 'desktop'; /* ---------------------------------------- @@ -87,7 +87,7 @@ Site ---------------------------------------- */ -$theme-site-max-width: "desktop"; -$theme-site-margins-breakpoint: "desktop"; +$theme-site-max-width: 'desktop'; +$theme-site-margins-breakpoint: 'desktop'; $theme-site-margins-width: 4; $theme-site-margins-mobile-width: 2; diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-typography.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-typography.scss index 19bdb5eb3..5046053d7 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-typography.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-typography.scss @@ -77,7 +77,7 @@ Relative font file path ---------------------------------------- */ -$theme-font-path: "../../../fonts"; +$theme-font-path: '../../../fonts'; /* ---------------------------------------- @@ -123,11 +123,11 @@ names to something more descriptive. $theme-typeface-tokens: ( example-serif-token: ( - display-name: "Example Serif Display Name", + display-name: 'Example Serif Display Name', cap-height: 364px, ), example-sans-token: ( - display-name: "Example Sans Display Name", + display-name: 'Example Sans Display Name', cap-height: 364px, ), ); @@ -164,13 +164,13 @@ $theme-font-type-icon: false; $theme-font-type-lang: false; // monospace -$theme-font-type-mono: "roboto-mono"; +$theme-font-type-mono: 'roboto-mono'; // sans-serif // $theme-font-type-sans: "source-sans-pro"; // serif -$theme-font-type-serif: "merriweather"; +$theme-font-type-serif: 'merriweather'; /* ---------------------------------------- @@ -283,11 +283,11 @@ tokens. ---------------------------------------- */ -$theme-font-role-ui: "sans"; -$theme-font-role-heading: "serif"; -$theme-font-role-body: "sans"; -$theme-font-role-code: "mono"; -$theme-font-role-alt: "serif"; +$theme-font-role-ui: 'sans'; +$theme-font-role-heading: 'serif'; +$theme-font-role-body: 'sans'; +$theme-font-role-code: 'mono'; +$theme-font-role-alt: 'serif'; /* ---------------------------------------- @@ -391,42 +391,42 @@ none: none */ // Body settings are the equivalent of setting the element -$theme-body-font-family: "body"; -$theme-body-font-size: "sm"; +$theme-body-font-family: 'body'; +$theme-body-font-size: 'sm'; $theme-body-line-height: 5; // If true, explicitly style the element with the base styles $theme-style-body-element: false; // Headings -$theme-h1-font-size: "2xl"; -$theme-h2-font-size: "xl"; -$theme-h3-font-size: "lg"; -$theme-h4-font-size: "sm"; -$theme-h5-font-size: "xs"; -$theme-h6-font-size: "3xs"; +$theme-h1-font-size: '2xl'; +$theme-h2-font-size: 'xl'; +$theme-h3-font-size: 'lg'; +$theme-h4-font-size: 'sm'; +$theme-h5-font-size: 'xs'; +$theme-h6-font-size: '3xs'; $theme-heading-line-height: 2; -$theme-small-font-size: "2xs"; -$theme-display-font-size: "3xl"; +$theme-small-font-size: '2xs'; +$theme-display-font-size: '3xl'; // Text and prose $theme-text-measure-narrow: 1; $theme-text-measure: 4; $theme-text-measure-wide: 6; -$theme-prose-font-family: "body"; +$theme-prose-font-family: 'body'; // Lead text -$theme-lead-font-family: "heading"; -$theme-lead-font-size: "lg"; +$theme-lead-font-family: 'heading'; +$theme-lead-font-size: 'lg'; $theme-lead-line-height: 6; $theme-lead-measure: 6; $theme-typeface-tokens: ( acf-arial: ( - display-name: "Arial", + display-name: 'Arial', cap-height: 345px, ), ); -$theme-font-type-sans: "acf-arial"; -$theme-font-sans-custom-stack: "Helvetica", sans; \ No newline at end of file +$theme-font-type-sans: 'acf-arial'; +$theme-font-sans-custom-stack: 'Helvetica', sans; diff --git a/tdrs-frontend/src/assets/uswds/_uswds-theme-utilities.scss b/tdrs-frontend/src/assets/uswds/_uswds-theme-utilities.scss index 95bdd966c..918f90bc6 100644 --- a/tdrs-frontend/src/assets/uswds/_uswds-theme-utilities.scss +++ b/tdrs-frontend/src/assets/uswds/_uswds-theme-utilities.scss @@ -31,23 +31,23 @@ used by utilities or layout grid */ $theme-utility-breakpoints: ( - "card": true, + 'card': true, // 160px - "card-lg": false, + 'card-lg': false, // 240px - "mobile": true, + 'mobile': true, // 320px - "mobile-lg": true, + 'mobile-lg': true, // 480px - "tablet": true, + 'tablet': true, // 640px - "tablet-lg": false, + 'tablet-lg': false, // 800px - "desktop": true, + 'desktop': true, // 1024px - "desktop-lg": false, + 'desktop-lg': false, // 1200px - "widescreen": false, + 'widescreen': false, // 1400px ); @@ -63,7 +63,7 @@ The following palettes will be added to ---------------------------------------- */ -$global-color-palettes: ("palette-color-default"); +$global-color-palettes: ('palette-color-default'); /* ---------------------------------------- @@ -588,7 +588,7 @@ $add-aspect-manual-values: (); // .align-items -$align-items-palettes: ("palette-align-items-default"); +$align-items-palettes: ('palette-align-items-default'); $align-items-manual-values: (); // .background-color @@ -598,7 +598,7 @@ $background-color-manual-values: (); // .border -$border-palettes: ("palette-border-default"); +$border-palettes: ('palette-border-default'); $border-manual-values: (); // .border-color @@ -608,35 +608,35 @@ $border-color-manual-values: (); // .border-radius -$border-radius-palettes: ("palette-border-radius-default"); +$border-radius-palettes: ('palette-border-radius-default'); $border-radius-manual-values: (); // .border-style -$border-style-palettes: ("palette-border-style-default"); +$border-style-palettes: ('palette-border-style-default'); $border-style-manual-values: (); // .border-width -$border-width-palettes: ("palette-border-width-default"); +$border-width-palettes: ('palette-border-width-default'); $border-width-manual-values: (); // .bottom -$bottom-palettes: ("palette-bottom-default"); +$bottom-palettes: ('palette-bottom-default'); $bottom-manual-values: (); // .box-shadow $box-shadow-palettes: (/* - */ "palette-box-shadow-default"); + */ 'palette-box-shadow-default'); $box-shadow-manual-values: (); // .circle -$circle-palettes: ("palette-circle-default"); +$circle-palettes: ('palette-circle-default'); $circle-manual-values: (); // .color @@ -646,171 +646,171 @@ $color-manual-values: (); // .cursor -$cursor-palettes: ("palette-cursor-default"); +$cursor-palettes: ('palette-cursor-default'); $cursor-manual-values: (); // .display -$display-palettes: ("palette-display-default"); +$display-palettes: ('palette-display-default'); $display-manual-values: (); // .flex -$flex-palettes: ("palette-flex-default"); +$flex-palettes: ('palette-flex-default'); $flex-manual-values: (); // .flex-direction -$flex-direction-palettes: ("palette-flex-direction-default"); +$flex-direction-palettes: ('palette-flex-direction-default'); $flex-direction-manual-values: (); // .flex-wrap -$flex-wrap-palettes: ("palette-flex-wrap-default"); +$flex-wrap-palettes: ('palette-flex-wrap-default'); $flex-wrap-manual-values: (); // .float -$float-palettes: ("palette-float-default"); +$float-palettes: ('palette-float-default'); $float-manual-values: (); // .font -$font-palettes: ("palette-font-default"); +$font-palettes: ('palette-font-default'); $font-manual-values: (); // .font-family -$font-family-palettes: ("palette-font-family-default"); +$font-family-palettes: ('palette-font-family-default'); $font-family-manual-values: (); // .font-feature-settings -$font-feature-palettes: ("palette-font-feature-settings-default"); +$font-feature-palettes: ('palette-font-feature-settings-default'); $font-feature-manual-values: (); // .font-style -$font-style-palettes: ("palette-font-style-default"); +$font-style-palettes: ('palette-font-style-default'); $font-style-manual-values: (); // .font-weight -$font-weight-palettes: ("palette-font-weight-default"); +$font-weight-palettes: ('palette-font-weight-default'); $font-weight-manual-values: (); // .height -$height-palettes: ("palette-height-default"); +$height-palettes: ('palette-height-default'); $height-manual-values: (); // .justify-content -$justify-content-palettes: ("palette-justify-content-default"); +$justify-content-palettes: ('palette-justify-content-default'); $justify-content-manual-values: (); // .left -$left-palettes: ("palette-left-default"); +$left-palettes: ('palette-left-default'); $left-manual-values: (); // .letter-spacing -$letter-spacing-palettes: ("palette-letter-spacing-default"); +$letter-spacing-palettes: ('palette-letter-spacing-default'); $letter-spacing-manual-values: (); // .line-height -$line-height-palettes: ("palette-line-height-default"); +$line-height-palettes: ('palette-line-height-default'); $line-height-manual-values: (); // .margin -$margin-palettes: ("palette-margin-default"); +$margin-palettes: ('palette-margin-default'); $margin-manual-values: (); -$margin-vertical-palettes: ("palette-margin-vertical-default"); +$margin-vertical-palettes: ('palette-margin-vertical-default'); $margin-vertical-manual-values: (); -$margin-horizontal-palettes: ("palette-margin-horizontal-default"); +$margin-horizontal-palettes: ('palette-margin-horizontal-default'); $margin-horizontal-manual-values: (); // .max-height -$max-height-palettes: ("palette-max-height-default"); +$max-height-palettes: ('palette-max-height-default'); $max-height-manual-values: (); // .max-width -$max-width-palettes: ("palette-max-width-default"); +$max-width-palettes: ('palette-max-width-default'); $max-width-manual-values: (); // .measure -$measure-palettes: ("palette-measure-default"); +$measure-palettes: ('palette-measure-default'); $measure-manual-values: (); // .min-height -$min-height-palettes: ("palette-min-height-default"); +$min-height-palettes: ('palette-min-height-default'); $min-height-manual-values: (); // .min-width -$min-width-palettes: ("palette-min-width-default"); +$min-width-palettes: ('palette-min-width-default'); $min-width-manual-values: (); // .opacity -$opacity-palettes: ("palette-opacity-default"); +$opacity-palettes: ('palette-opacity-default'); $opacity-manual-values: (); // .order -$order-palettes: ("palette-order-default"); +$order-palettes: ('palette-order-default'); $order-manual-values: (); // .outline -$outline-palettes: ("palette-outline-default"); +$outline-palettes: ('palette-outline-default'); $outline-manual-values: (); // .outline-color -$outline-color-palettes: ("palette-outline-color-default"); +$outline-color-palettes: ('palette-outline-color-default'); $outline-color-manual-values: (); // .overflow -$overflow-palettes: ("palette-overflow-default"); +$overflow-palettes: ('palette-overflow-default'); $overflow-manual-values: (); // .padding -$padding-palettes: ("palette-padding-default"); +$padding-palettes: ('palette-padding-default'); $padding-manual-values: (); // .position -$position-palettes: ("palette-position-default"); +$position-palettes: ('palette-position-default'); $position-manual-values: (); // .right -$right-palettes: ("palette-right-default"); +$right-palettes: ('palette-right-default'); $right-manual-values: (); // .square -$square-palettes: ("palette-square-default"); +$square-palettes: ('palette-square-default'); $square-manual-values: (); // .text-align -$text-align-palettes: ("palette-text-align-default"); +$text-align-palettes: ('palette-text-align-default'); $text-align-manual-values: (); // .text-decoration -$text-decoration-palettes: ("palette-text-decoration-default"); +$text-decoration-palettes: ('palette-text-decoration-default'); $text-decoration-manual-values: (); // .text-decoration-color @@ -820,35 +820,35 @@ $text-decoration-color-manual-values: (); // .text-indent -$text-indent-palettes: ("palette-text-indent-default"); +$text-indent-palettes: ('palette-text-indent-default'); $text-indent-manual-values: (); // .text-transform -$text-transform-palettes: ("palette-text-transform-default"); +$text-transform-palettes: ('palette-text-transform-default'); $text-transform-manual-values: (); // .top -$top-palettes: ("palette-top-default"); +$top-palettes: ('palette-top-default'); $top-manual-values: (); // .vertical-align -$vertical-align-palettes: ("palette-vertical-align-default"); +$vertical-align-palettes: ('palette-vertical-align-default'); $vertical-align-manual-values: (); // .white-space -$whitespace-palettes: ("palette-white-space-default"); +$whitespace-palettes: ('palette-white-space-default'); $whitespace-manual-values: (); // .width -$width-palettes: ("palette-width-default"); +$width-palettes: ('palette-width-default'); $width-manual-values: (); // .z-index -$z-index-palettes: ("palette-z-index-default"); +$z-index-palettes: ('palette-z-index-default'); $z-index-manual-values: (); diff --git a/tdrs-frontend/src/components/FileUpload/FileUpload.jsx b/tdrs-frontend/src/components/FileUpload/FileUpload.jsx index 343f4b63d..ec71cc772 100644 --- a/tdrs-frontend/src/components/FileUpload/FileUpload.jsx +++ b/tdrs-frontend/src/components/FileUpload/FileUpload.jsx @@ -18,50 +18,131 @@ import { clearError, upload, download } from '../../actions/reports' import Button from '../Button' -// helpers -const getReports = (state) => state.reports -const toLower = (s) => s.toLowerCase() - -const initiateDownloadSequence = ({ - data, - year, - quarter, - section, - canDownload, -}) => () => { - if (canDownload) { - const url = window.URL.createObjectURL(new Blob([data])) - const link = document.createElement('a') +const SPACER_GIF = + "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; +const LOADING_CLASS = "is-loading"; +const GENERIC_PREVIEW_CLASS_NAME = `${PREFIX}-file-input__preview-image`; + +const handleChange = (e, fileInputEl, instructions, dropTarget) => { + const fileNames = e.target.files; + const filePreviewsHeading = document.createElement("div"); + + // First, get rid of existing previews + removeOldPreviews(dropTarget, instructions); + + // Iterates through files list and creates previews + for (let i = 0; i < fileNames.length; i += 1) { + const reader = new FileReader(); + const fileName = fileNames[i].name; + + // Starts with a loading image while preview is created + reader.onloadstart = function createLoadingImage() { + const imageId = makeSafeForID(fileName); + const previewImage = ``; + + instructions.insertAdjacentHTML( + "afterend", + `