diff --git a/cypress/e2e/Settings/settings.spec.js b/cypress/e2e/Settings/settings.spec.js
index dbcca15f..cbd8cd96 100644
--- a/cypress/e2e/Settings/settings.spec.js
+++ b/cypress/e2e/Settings/settings.spec.js
@@ -14,6 +14,7 @@ import {
updateMaxRateLimit,
updateAutoAcceptIncidentQuery,
updateAutoRefreshInterval,
+ updateDarkMode,
manageIncidentTableColumns,
manageCustomAlertColumnDefinitions,
activateButton,
@@ -193,4 +194,16 @@ describe('Manage Settings', { failFast: { enabled: false } }, () => {
cy.get('.btn').contains('Clear Local Cache').click();
cy.get('.modal-title').contains('Disclaimer & License').should('be.visible');
});
+
+ it('Update dark mode', () => {
+ [true, false].forEach((darkMode) => {
+ updateDarkMode(darkMode);
+ cy.window()
+ .its('store')
+ .invoke('getState')
+ .then((state) => expect(
+ state.settings.darkMode,
+ ).to.equal(darkMode));
+ });
+ });
});
diff --git a/cypress/support/util/common.js b/cypress/support/util/common.js
index b683b5b7..c8bff941 100644
--- a/cypress/support/util/common.js
+++ b/cypress/support/util/common.js
@@ -305,6 +305,22 @@ export const updateAutoAcceptIncidentQuery = (autoAcceptIncidentsQuery = false)
cy.get('.close').click();
};
+export const updateDarkMode = (darkMode = false) => {
+ cy.get('.settings-panel-dropdown').click();
+ cy.get('.dropdown-item').contains('Settings').click();
+ cy.get('.nav-item').contains('User Profile').click();
+
+ if (darkMode) {
+ cy.get('#user-profile-dark-mode-checkbox').check({ force: true });
+ } else {
+ cy.get('#user-profile-dark-mode-checkbox').uncheck({ force: true });
+ }
+
+ cy.get('.btn').contains('Update User Profile').click();
+ checkActionAlertsModalContent('Updated user profile settings');
+ cy.get('.close').click();
+};
+
export const priorityNames = ['--', 'P5', 'P4', 'P3', 'P2', 'P1'];
/*
diff --git a/src/App.js b/src/App.js
index 9cbbee7c..4bafb02e 100644
--- a/src/App.js
+++ b/src/App.js
@@ -97,6 +97,14 @@ const App = ({
}) => {
// Verify if session token is present
const token = sessionStorage.getItem('pd_access_token');
+ const {
+ autoRefreshInterval, darkMode,
+ } = state.settings;
+
+ if (darkMode) {
+ document.body.classList.add('dark-mode');
+ }
+
if (!token) {
return (
@@ -109,9 +117,6 @@ const App = ({
const {
userAuthorized, userAcceptedDisclaimer, currentUserLocale,
} = state.users;
- const {
- autoRefreshInterval,
- } = state.settings;
const {
fetchingIncidents,
fetchingIncidentNotes,
diff --git a/src/App.scss b/src/App.scss
index a5c82ee1..87d4429d 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -5,12 +5,22 @@ body {
background-color: $pd-brand-background !important;
}
+body.dark-mode {
+ background-color: $pd-brand-gray-dark !important;
+}
+
.btn-outline-secondary {
color: $pd-brand-black;
background-color: $pd-brand-white;
border-color: $pd-brand-secondary-light;
}
+body.dark-mode .btn-outline-secondary {
+ color: $pd-white;
+ background-color: $pd-brand-gray-dark;
+ border-color: $pd-brand-secondary-light;
+}
+
.btn-outline-secondary:disabled {
color: $pd-brand-secondary-light !important;
}
@@ -26,6 +36,10 @@ body {
background-color: unset !important;
}
+body.dark-mode .btn-outline-secondary:not(:disabled):not(.disabled).active {
+ background-color: $pd-brand-gray-light !important;
+}
+
.btn-outline-dark {
color: $pd-brand-gray-dark;
background-color: $pd-white;
@@ -59,3 +73,54 @@ body {
.modal-footer {
display: unset !important;
}
+
+body.dark-mode a {
+ color: $pd-brand-white;
+}
+
+body.dark-mode .modal-content {
+ background-color: $pd-brand-black !important;
+ color: $pd-white !important;
+}
+
+body.dark-mode .modal-title {
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode .modal-header .close {
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode .form-label, body.dark-mode .form-text {
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode .form-control {
+ background-color: $pd-brand-gray-dark !important;
+ color: $pd-white;
+}
+
+body.dark-mode div.react-select__control, body.dark-mode div.react-select__menu {
+ background-color: $pd-brand-gray-dark !important;
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode div.react-select__multi-value {
+ background-color: $pd-brand-gray-light !important;
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode div.react-select__single-value {
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode div.react-select__option:hover {
+ background-color: $pd-brand-secondary-light !important;
+ color: $pd-brand-white !important;
+}
+
+body.dark-mode div.react-select__option--is-focused {
+ background-color: $pd-brand-secondary-light !important;
+ color: $pd-brand-white !important;
+}
+
diff --git a/src/assets/images/pd_logo_white.svg b/src/assets/images/pd_logo_white.svg
new file mode 100644
index 00000000..1394a06d
--- /dev/null
+++ b/src/assets/images/pd_logo_white.svg
@@ -0,0 +1,37 @@
+
+
+
diff --git a/src/components/AddResponderModal/AddResponderModalComponent.js b/src/components/AddResponderModal/AddResponderModalComponent.js
index 21dc4fc1..9c571c76 100644
--- a/src/components/AddResponderModal/AddResponderModalComponent.js
+++ b/src/components/AddResponderModal/AddResponderModalComponent.js
@@ -86,6 +86,7 @@ const AddResponderModalComponent = ({
{t('Responders')}