diff --git a/SQL/0000-00-00-schema.sql b/SQL/0000-00-00-schema.sql
index ef0a7c39504..3196f384902 100644
--- a/SQL/0000-00-00-schema.sql
+++ b/SQL/0000-00-00-schema.sql
@@ -1426,6 +1426,38 @@ CREATE TABLE `user_account_history` (
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ********************************
+-- tables for policies
+-- ********************************
+
+CREATE TABLE policies (
+ PolicyID INT AUTO_INCREMENT PRIMARY KEY,
+ Name VARCHAR(255) NOT NULL,
+ Version INT NOT NULL,
+ ModuleID INT NOT NULL,
+ PolicyRenewalTime INT DEFAULT 7,
+ PolicyRenewalTimeUnit enum('D','Y','M','H') DEFAULT 'D',
+ Content TEXT NULL,
+ SwalTitle VARCHAR(255) DEFAULT 'Terms of Use',
+ HeaderButton enum('Y','N') DEFAULT 'Y',
+ HeaderButtonText VARCHAR(255) DEFAULT 'Terms of Use',
+ Active enum('Y','N') DEFAULT 'Y',
+ AcceptButtonText VARCHAR(255) DEFAULT 'Accept',
+ DeclineButtonText VARCHAR(255) DEFAULT 'Decline',
+ CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
+ UpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+
+CREATE TABLE user_policy_decision (
+ ID INT AUTO_INCREMENT PRIMARY KEY,
+ UserID INT NOT NULL,
+ PolicyID INT NOT NULL,
+ Decision enum('Accepted','Declined') NOT NULL,
+ DecisionDate DATETIME DEFAULT CURRENT_TIMESTAMP
+);
+
+
-- ********************************
-- user_login_history tables
-- ********************************
diff --git a/SQL/0000-00-01-Modules.sql b/SQL/0000-00-01-Modules.sql
index 2562b9ae10e..f69435841e6 100644
--- a/SQL/0000-00-01-Modules.sql
+++ b/SQL/0000-00-01-Modules.sql
@@ -55,5 +55,6 @@ INSERT INTO modules (Name, Active) VALUES ('electrophysiology_uploader', 'Y');
INSERT INTO modules (Name, Active) VALUES ('dataquery', 'Y');
INSERT INTO modules (Name, Active) VALUES ('schedule_module', 'Y');
INSERT INTO modules (Name, Active) VALUES ('redcap', 'N');
+INSERT INTO modules (Name, Active) VALUES ('policy_tracker', 'Y');
ALTER TABLE issues ADD CONSTRAINT `fk_issues_7` FOREIGN KEY (`module`) REFERENCES `modules` (`ID`);
diff --git a/SQL/9999-99-99-drop_tables.sql b/SQL/9999-99-99-drop_tables.sql
index c5579986fff..fcfbe35409f 100644
--- a/SQL/9999-99-99-drop_tables.sql
+++ b/SQL/9999-99-99-drop_tables.sql
@@ -133,6 +133,8 @@ DROP TABLE IF EXISTS `server_processes`;
DROP TABLE IF EXISTS `StatisticsTabs`;
DROP TABLE IF EXISTS `user_login_history`;
DROP TABLE IF EXISTS `user_account_history`;
+DROP TABLE IF EXISTS `policies`;
+DROP TABLE IF EXISTS `user_policy_decision`;
DROP TABLE IF EXISTS `data_integrity_flag`;
DROP TABLE IF EXISTS `certification_training_quiz_answers`;
DROP TABLE IF EXISTS `certification_training_quiz_questions`;
diff --git a/SQL/New_patches/2025-05-22-Introduce-Policy-Decisions.sql b/SQL/New_patches/2025-05-22-Introduce-Policy-Decisions.sql
new file mode 100644
index 00000000000..a66662c05b8
--- /dev/null
+++ b/SQL/New_patches/2025-05-22-Introduce-Policy-Decisions.sql
@@ -0,0 +1,27 @@
+CREATE TABLE policies (
+ PolicyID INT AUTO_INCREMENT PRIMARY KEY,
+ Name VARCHAR(255) NOT NULL,
+ Version INT NOT NULL,
+ ModuleID INT NOT NULL, -- Show in the header for a module
+ PolicyRenewalTime INT DEFAULT 7, -- Number of days before the policy is renewed
+ PolicyRenewalTimeUnit enum('D','Y','M','H') DEFAULT 'D', -- Unit of the renewal time
+ Content TEXT NULL,
+ SwalTitle VARCHAR(255) DEFAULT 'Terms of Use',
+ HeaderButton enum('Y','N') DEFAULT 'Y',
+ HeaderButtonText VARCHAR(255) DEFAULT 'Terms of Use',
+ Active enum('Y','N') DEFAULT 'Y',
+ AcceptButtonText VARCHAR(255) DEFAULT 'Accept',
+ DeclineButtonText VARCHAR(255) DEFAULT 'Decline',
+ CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
+ UpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+
+CREATE TABLE user_policy_decision (
+ ID INT AUTO_INCREMENT PRIMARY KEY,
+ UserID INT NOT NULL,
+ PolicyID INT NOT NULL,
+ Decision enum('Accepted','Declined') NOT NULL,
+ DecisionDate DATETIME DEFAULT CURRENT_TIMESTAMP
+);
+
+INSERT INTO modules (`Name`, `Active`) VALUES ('policy_tracker','Y');
\ No newline at end of file
diff --git a/SQL/sql_for_abstract.sql b/SQL/sql_for_abstract.sql
new file mode 100644
index 00000000000..60626afddb8
--- /dev/null
+++ b/SQL/sql_for_abstract.sql
@@ -0,0 +1,391 @@
+SELECT count(DISTINCT cr.ResolvedID)
+FROM conflicts_resolved cr
+JOIN (
+ SELECT f.CommentID
+ FROM flag f
+ JOIN session s ON f.SessionID = s.ID
+ WHERE s.Visit_label IN (
+ 'Initial_Assessment_Screening',
+ 'Initial_MRI',
+ 'Repeat_Initial_Assessment_Screening',
+ 'Clinical_Assessment',
+ 'Neuropsychology_Assessment'
+ )
+ -- AND s.SubprojectID IN (1,2,3,4,5,6,7,8,9,10,14,17,18)
+ AND Test_name NOT IN (
+'Annual_Follow_up_Phone_Call',
+'Autopsy_Banked_Tissue_Inventory',
+'Autopsy_Neuropathology_Report',
+'Clinical_Current_Medication',
+'Clinical_Current_Medication_FU',
+'Clinical_Diagnosis_Confirmation',
+'Clinical_Family_History',
+'Clinical_Family_History_FU',
+'Clinical_Hobbies_And_Leisure_Activities',
+'Clinical_Initial_Symptoms',
+'Clinical_Lumbar_Puncture_Procedure_Report',
+'Clinical_Medical_History',
+'Clinical_Medical_History_FU',
+'Clinical_Mental_Health_History',
+'Clinical_Mental_Health_History_FU',
+'Clinical_Past_Medications',
+'Clinical_Past_Medications_FU',
+'Clinical_Pre_Gait_Assessment',
+'Clinical_Signs_Symptoms',
+'Clinical_Sleep_Work_Diary',
+'Clinical_Smoking',
+'Clinical_Surgical_History',
+'Clinical_Surgical_History_FU',
+'Clinical_UPDRS_III_IV',
+'General_Health_Alcohol_Consumption',
+'General_Health_Biosample_Collection',
+'General_Health_Caregiving_Assessment',
+'General_Health_Falls_Balance',
+'General_Health_Gait_Assessment',
+'General_Health_Grip_Strength',
+'General_Health_Nutrition',
+'General_Health_Physical_Activity',
+'General_Health_Physical_Activity_FU',
+'General_Health_Sleep',
+'General_Health_Vision',
+'mri_parameter_form',
+'PI_Caregiving_Assessment',
+'PI_General_Information',
+'PI_General_Information_FU',
+'Reappraisal_Initial_Diagnosis_Reappraisal',
+'Reappraisal_Initial_Diagnosis_Reappraisal_IMPACT_AD',
+'Screening_CERAD_Recog',
+'Screening_Driving_History',
+'Screening_Driving_History_FU',
+'Screening_Education',
+'Screening_Education_FU',
+'Screening_Employment_History',
+'Screening_Employment_History_FU',
+'Screening_Languages',
+'Screening_Logical_Memory_Delayed',
+'Screening_MOCA',
+'Screening_Reproductive_History'
+)
+) fs ON fs.CommentID = cr.CommentID1;
+
+SELECT count(*)
+FROM information_schema.columns
+WHERE table_name NOT IN (
+'Annual_Follow_up_Phone_Call',
+'Autopsy_Banked_Tissue_Inventory',
+'Autopsy_Neuropathology_Report',
+'Clinical_Current_Medication',
+'Clinical_Current_Medication_FU',
+'Clinical_Diagnosis_Confirmation',
+'Clinical_Family_History',
+'Clinical_Family_History_FU',
+'Clinical_Hobbies_And_Leisure_Activities',
+'Clinical_Initial_Symptoms',
+'Clinical_Lumbar_Puncture_Procedure_Report',
+'Clinical_Medical_History',
+'Clinical_Medical_History_FU',
+'Clinical_Mental_Health_History',
+'Clinical_Mental_Health_History_FU',
+'Clinical_Past_Medications',
+'Clinical_Past_Medications_FU',
+'Clinical_Pre_Gait_Assessment',
+'Clinical_Signs_Symptoms',
+'Clinical_Sleep_Work_Diary',
+'Clinical_Smoking',
+'Clinical_Surgical_History',
+'Clinical_Surgical_History_FU',
+'Clinical_UPDRS_III_IV',
+'General_Health_Alcohol_Consumption',
+'General_Health_Biosample_Collection',
+'General_Health_Caregiving_Assessment',
+'General_Health_Falls_Balance',
+'General_Health_Gait_Assessment',
+'General_Health_Grip_Strength',
+'General_Health_Nutrition',
+'General_Health_Physical_Activity',
+'General_Health_Physical_Activity_FU',
+'General_Health_Sleep',
+'General_Health_Vision',
+'mri_parameter_form',
+'PI_Caregiving_Assessment',
+'PI_General_Information',
+'PI_General_Information_FU',
+'Reappraisal_Initial_Diagnosis_Reappraisal',
+'Reappraisal_Initial_Diagnosis_Reappraisal_IMPACT_AD',
+'Screening_CERAD_Recog',
+'Screening_Driving_History',
+'Screening_Driving_History_FU',
+'Screening_Education',
+'Screening_Education_FU',
+'Screening_Employment_History',
+'Screening_Employment_History_FU',
+'Screening_Languages',
+'Screening_Logical_Memory_Delayed',
+'Screening_MOCA',
+'Screening_Reproductive_History'
+)
+
+SELECT count(DISTINCT cr.ConflictID)
+FROM conflicts_unresolved cr
+JOIN (
+ SELECT f.CommentID
+ FROM flag f
+ JOIN session s ON f.SessionID = s.ID
+ WHERE s.Visit_label LIKE '%Time_3%'
+ -- AND s.SubprojectID IN (1,2,3,4,5,6,7,8,9,10,14,17,18)
+-- AND Test_name NOT IN (
+-- 'Annual_Follow_up_Phone_Call',
+-- 'Autopsy_Banked_Tissue_Inventory',
+-- 'Autopsy_Neuropathology_Report',
+-- 'Clinical_Current_Medication',
+-- 'Clinical_Current_Medication_FU',
+-- 'Clinical_Diagnosis_Confirmation',
+-- 'Clinical_Family_History',
+-- 'Clinical_Family_History_FU',
+-- 'Clinical_Hobbies_And_Leisure_Activities',
+-- 'Clinical_Initial_Symptoms',
+-- 'Clinical_Lumbar_Puncture_Procedure_Report',
+-- 'Clinical_Medical_History',
+-- 'Clinical_Medical_History_FU',
+-- 'Clinical_Mental_Health_History',
+-- 'Clinical_Mental_Health_History_FU',
+-- 'Clinical_Past_Medications',
+-- 'Clinical_Past_Medications_FU',
+-- 'Clinical_Pre_Gait_Assessment',
+-- 'Clinical_Signs_Symptoms',
+-- 'Clinical_Sleep_Work_Diary',
+-- 'Clinical_Smoking',
+-- 'Clinical_Surgical_History',
+-- 'Clinical_Surgical_History_FU',
+-- 'Clinical_UPDRS_III_IV',
+-- 'General_Health_Alcohol_Consumption',
+-- 'General_Health_Biosample_Collection',
+-- 'General_Health_Caregiving_Assessment',
+-- 'General_Health_Falls_Balance',
+-- 'General_Health_Gait_Assessment',
+-- 'General_Health_Grip_Strength',
+-- 'General_Health_Nutrition',
+-- 'General_Health_Physical_Activity',
+-- 'General_Health_Physical_Activity_FU',
+-- 'General_Health_Sleep',
+-- 'General_Health_Vision',
+-- 'mri_parameter_form',
+-- 'PI_Caregiving_Assessment',
+-- 'PI_General_Information',
+-- 'PI_General_Information_FU',
+-- 'Reappraisal_Initial_Diagnosis_Reappraisal',
+-- 'Reappraisal_Initial_Diagnosis_Reappraisal_IMPACT_AD',
+-- 'Screening_CERAD_Recog',
+-- 'Screening_Driving_History',
+-- 'Screening_Driving_History_FU',
+-- 'Screening_Education',
+-- 'Screening_Education_FU',
+-- 'Screening_Employment_History',
+-- 'Screening_Employment_History_FU',
+-- 'Screening_Languages',
+-- 'Screening_Logical_Memory_Delayed',
+-- 'Screening_MOCA',
+-- 'Screening_Reproductive_History'
+-- )
+) fs ON fs.CommentID = cr.CommentID1;
+
+SELECT count(f.CommentID)
+ FROM flag f
+ JOIN session s ON f.SessionID = s.ID
+ WHERE s.Visit_label IN (
+ 'Initial_Assessment_Screening',
+ 'Initial_MRI',
+ 'Repeat_Initial_Assessment_Screening',
+ 'Clinical_Assessment',
+ 'Neuropsychology_Assessment'
+ )
+ AND CommentID LIKE 'DDE_%'
+ AND Data_entry IS NOT NULL
+ -- AND s.SubprojectID IN (1,2,3,4,5,6,7,8,9,10,14,17,18)
+ AND Test_name NOT IN (
+ 'Annual_Follow_up_Phone_Call',
+ 'Autopsy_Banked_Tissue_Inventory'
+ 'Autopsy_Neuropathology_Report',
+ 'Clinical_Current_Medication',
+ 'Clinical_Current_Medication_FU',
+ 'Clinical_Diagnosis_Confirmation',
+ 'Clinical_Family_History',
+ 'Clinical_Family_History_FU',
+ 'Clinical_Hobbies_And_Leisure_Activities',
+ 'Clinical_Initial_Symptoms',
+ 'Clinical_Lumbar_Puncture_Procedure_Report',
+ 'Clinical_Medical_History',
+ 'Clinical_Medical_History_FU',
+ 'Clinical_Mental_Health_History',
+ 'Clinical_Mental_Health_History_FU',
+ 'Clinical_Past_Medications',
+ 'Clinical_Past_Medications_FU',
+ 'Clinical_Pre_Gait_Assessment',
+ 'Clinical_Signs_Symptoms',
+ 'Clinical_Sleep_Work_Diary',
+ 'Clinical_Smoking',
+ 'Clinical_Surgical_History',
+ 'Clinical_Surgical_History_FU',
+ 'Clinical_UPDRS_III_IV',
+ 'General_Health_Alcohol_Consumption',
+ 'General_Health_Biosample_Collection',
+ 'General_Health_Caregiving_Assessment',
+ 'General_Health_Falls_Balance',
+ 'General_Health_Gait_Assessment',
+ 'General_Health_Grip_Strength',
+ 'General_Health_Nutrition',
+ 'General_Health_Physical_Activity',
+ 'General_Health_Physical_Activity_FU',
+ 'General_Health_Sleep',
+ 'General_Health_Vision',
+ 'mri_parameter_form',
+ 'PI_Caregiving_Assessment',
+ 'PI_General_Information',
+ 'PI_General_Information_FU',
+ 'Reappraisal_Initial_Diagnosis_Reappraisal',
+ 'Reappraisal_Initial_Diagnosis_Reappraisal_IMPACT_AD',
+ 'Screening_CERAD_Recog',
+ 'Screening_Driving_History',
+ 'Screening_Driving_History_FU',
+ 'Screening_Education',
+ 'Screening_Education_FU',
+ 'Screening_Employment_History',
+ 'Screening_Employment_History_FU',
+ 'Screening_Languages',
+ 'Screening_Logical_Memory_Delayed',
+ 'Screening_MOCA',
+ 'Screening_Reproductive_History'
+ );
+
+ SELECT count(f.CommentID)
+ FROM flag f
+ JOIN session s ON f.SessionID = s.ID
+ WHERE s.Visit_label LIKE '%Time_3%'
+ AND Data_entry IS NOT NULL
+ AND CommentID LIKE 'DDE_%'
+ -- AND s.SubprojectID IN (1,2,3,4,5,6,7,8,9,10,14,17,18)
+ AND Test_name NOT IN (
+ 'Annual_Follow_up_Phone_Call',
+ 'Autopsy_Banked_Tissue_Inventory',
+ 'Autopsy_Neuropathology_Report',
+ 'Clinical_Current_Medication',
+ 'Clinical_Current_Medication_FU',
+ 'Clinical_Diagnosis_Confirmation',
+ 'Clinical_Family_History',
+ 'Clinical_Family_History_FU',
+ 'Clinical_Hobbies_And_Leisure_Activities',
+ 'Clinical_Initial_Symptoms',
+ 'Clinical_Lumbar_Puncture_Procedure_Report',
+ 'Clinical_Medical_History',
+ 'Clinical_Medical_History_FU',
+ 'Clinical_Mental_Health_History',
+ 'Clinical_Mental_Health_History_FU',
+ 'Clinical_Past_Medications',
+ 'Clinical_Past_Medications_FU',
+ 'Clinical_Pre_Gait_Assessment',
+ 'Clinical_Signs_Symptoms',
+ 'Clinical_Sleep_Work_Diary',
+ 'Clinical_Smoking',
+ 'Clinical_Surgical_History',
+ 'Clinical_Surgical_History_FU',
+ 'Clinical_UPDRS_III_IV',
+ 'General_Health_Alcohol_Consumption',
+ 'General_Health_Biosample_Collection',
+ 'General_Health_Caregiving_Assessment',
+ 'General_Health_Falls_Balance',
+ 'General_Health_Gait_Assessment',
+ 'General_Health_Grip_Strength',
+ 'General_Health_Nutrition',
+ 'General_Health_Physical_Activity',
+ 'General_Health_Physical_Activity_FU',
+ 'General_Health_Sleep',
+ 'General_Health_Vision',
+ 'mri_parameter_form',
+ 'PI_Caregiving_Assessment',
+ 'PI_General_Information',
+ 'PI_General_Information_FU',
+ 'Reappraisal_Initial_Diagnosis_Reappraisal',
+ 'Reappraisal_Initial_Diagnosis_Reappraisal_IMPACT_AD',
+ 'Screening_CERAD_Recog',
+ 'Screening_Driving_History',
+ 'Screening_Driving_History_FU',
+ 'Screening_Education',
+ 'Screening_Education_FU',
+ 'Screening_Employment_History',
+ 'Screening_Employment_History_FU',
+ 'Screening_Languages',
+ 'Screening_Logical_Memory_Delayed',
+ 'Screening_MOCA',
+ 'Screening_Reproductive_History'
+ )
+
+
+SELECT med_name, COUNT(*) AS total_count
+FROM (
+ SELECT med_name_1 AS med_name FROM Clinical_Current_Medication WHERE med_name_1 IS NOT NULL
+ UNION ALL
+ SELECT med_name_2 FROM Clinical_Current_Medication WHERE med_name_2 IS NOT NULL
+ UNION ALL
+ SELECT med_name_3 FROM Clinical_Current_Medication WHERE med_name_3 IS NOT NULL
+ UNION ALL
+ SELECT med_name_4 FROM Clinical_Current_Medication WHERE med_name_4 IS NOT NULL
+ UNION ALL
+ SELECT med_name_5 FROM Clinical_Current_Medication WHERE med_name_5 IS NOT NULL
+ UNION ALL
+ SELECT med_name_6 FROM Clinical_Current_Medication WHERE med_name_6 IS NOT NULL
+ UNION ALL
+ SELECT med_name_7 FROM Clinical_Current_Medication WHERE med_name_7 IS NOT NULL
+ UNION ALL
+ SELECT med_name_8 FROM Clinical_Current_Medication WHERE med_name_8 IS NOT NULL
+ -- Continue this pattern up to med_name_32
+ UNION ALL
+ SELECT med_name_9 FROM Clinical_Current_Medication WHERE med_name_9 IS NOT NULL
+ UNION ALL
+ SELECT med_name_10 FROM Clinical_Current_Medication WHERE med_name_10 IS NOT NULL
+ UNION ALL
+ SELECT med_name_11 FROM Clinical_Current_Medication WHERE med_name_11 IS NOT NULL
+ UNION ALL
+ SELECT med_name_12 FROM Clinical_Current_Medication WHERE med_name_12 IS NOT NULL
+ UNION ALL
+ SELECT med_name_13 FROM Clinical_Current_Medication WHERE med_name_13 IS NOT NULL
+ UNION ALL
+ SELECT med_name_14 FROM Clinical_Current_Medication WHERE med_name_14 IS NOT NULL
+ UNION ALL
+ SELECT med_name_15 FROM Clinical_Current_Medication WHERE med_name_15 IS NOT NULL
+ UNION ALL
+ SELECT med_name_16 FROM Clinical_Current_Medication WHERE med_name_16 IS NOT NULL
+ UNION ALL
+ SELECT med_name_17 FROM Clinical_Current_Medication WHERE med_name_17 IS NOT NULL
+ UNION ALL
+ SELECT med_name_18 FROM Clinical_Current_Medication WHERE med_name_18 IS NOT NULL
+ UNION ALL
+ SELECT med_name_19 FROM Clinical_Current_Medication WHERE med_name_19 IS NOT NULL
+ UNION ALL
+ SELECT med_name_20 FROM Clinical_Current_Medication WHERE med_name_20 IS NOT NULL
+ UNION ALL
+ SELECT med_name_21 FROM Clinical_Current_Medication WHERE med_name_21 IS NOT NULL
+ UNION ALL
+ SELECT med_name_22 FROM Clinical_Current_Medication WHERE med_name_22 IS NOT NULL
+ UNION ALL
+ SELECT med_name_23 FROM Clinical_Current_Medication WHERE med_name_23 IS NOT NULL
+ UNION ALL
+ SELECT med_name_24 FROM Clinical_Current_Medication WHERE med_name_24 IS NOT NULL
+ UNION ALL
+ SELECT med_name_25 FROM Clinical_Current_Medication WHERE med_name_25 IS NOT NULL
+ UNION ALL
+ SELECT med_name_26 FROM Clinical_Current_Medication WHERE med_name_26 IS NOT NULL
+ UNION ALL
+ SELECT med_name_27 FROM Clinical_Current_Medication WHERE med_name_27 IS NOT NULL
+ UNION ALL
+ SELECT med_name_28 FROM Clinical_Current_Medication WHERE med_name_28 IS NOT NULL
+ UNION ALL
+ SELECT med_name_29 FROM Clinical_Current_Medication WHERE med_name_29 IS NOT NULL
+ UNION ALL
+ SELECT med_name_30 FROM Clinical_Current_Medication WHERE med_name_30 IS NOT NULL
+ UNION ALL
+ SELECT med_name_31 FROM Clinical_Current_Medication WHERE med_name_31 IS NOT NULL
+ UNION ALL
+ SELECT med_name_32 FROM Clinical_Current_Medication WHERE med_name_32 IS NOT NULL
+) AS all_meds
+GROUP BY med_name
+ORDER BY total_count DESC;
diff --git a/jsx/PolicyButton.js b/jsx/PolicyButton.js
new file mode 100644
index 00000000000..f31921d7ee6
--- /dev/null
+++ b/jsx/PolicyButton.js
@@ -0,0 +1,108 @@
+/**
+ * This file contains React component for the Policy Button.
+ *
+ * @author Saagar Arya
+ * @version 2.0.0
+ */
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import Swal from 'sweetalert2';
+
+/**
+ * PolicyButton Component
+ *
+ * @param {object} props - The component props.
+ * @param {object} props.onClickPolicy - The policy object containing title
+ * and content that should appear when the button is pressed.
+ * @param {object} [props.buttonStyle] - Optional style object for the button.
+ * @param {object} [props.popUpPolicy] - Optional policy object for pop-up
+ * policy that needs renewal.
+ * @param {string} [props.buttonText] - Optional text for the button.
+ * @param {boolean} [props.anon] - Optional flag to indicate if the user is anonymous.
+ * @param {function} [props.callback] - Optional callback function to execute after the policy decision.
+ */
+const PolicyButton = ({
+ onClickPolicy,
+ popUpPolicy,
+ buttonStyle,
+ buttonText,
+ anon=false,
+ callback=() => {},
+}) => {
+ if (popUpPolicy && popUpPolicy.needsRenewal) {
+ fireSwal(popUpPolicy);
+ }
+ if (onClickPolicy) {
+ return {
+ fireSwal(onClickPolicy, anon, callback);
+ }}
+ >
+ {buttonText || onClickPolicy.HeaderButtonText}
+ ;
+ }
+};
+
+const fireSwal = (policy, anon, callback) => {
+ Swal.fire({
+ title: policy.SwalTitle,
+ html: policy.Content,
+ confirmButtonText: policy.AcceptButtonText,
+ cancelButtonText: policy.DeclineButtonText,
+ showCancelButton: policy.DeclineButtonText,
+ allowOutsideClick: false,
+ }).then((decision) => {
+ if (callback) {
+ callback(decision);
+ }
+ if (!anon) {
+ fetch(
+ loris.BaseURL +
+ '/policy_tracker/policies',
+ {
+ method: 'POST',
+ credentials: 'same-origin',
+ body: JSON.stringify({
+ ...policy,
+ decision: decision.value == true ? 'Accepted' : 'Declined',
+ }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ if (decision.value != true) {
+ window.location.href = loris.BaseURL;
+ }
+ }
+ });
+};
+
+PolicyButton.propTypes = {
+ onClickPolicy: PropTypes.shape({
+ SwalTitle: PropTypes.string.isRequired,
+ Content: PropTypes.string.isRequired,
+ AcceptButtonText: PropTypes.string.isRequired,
+ DeclineButtonText: PropTypes.string.isRequired,
+ }).isRequired,
+ onClickPolicy: PropTypes.object.isRequired,
+ popUpPolicy: PropTypes.shape({
+ needsRenewal: PropTypes.bool,
+ SwalTitle: PropTypes.string,
+ Content: PropTypes.string,
+ AcceptButtonText: PropTypes.string,
+ DeclineButtonText: PropTypes.string,
+ }),
+ buttonStyle: PropTypes.object,
+ buttonText: PropTypes.string,
+ anon: PropTypes.bool,
+ callback: PropTypes.func,
+};
+
+window.PolicyButton = PolicyButton;
+
+export {PolicyButton, fireSwal};
diff --git a/modules/login/jsx/loginIndex.js b/modules/login/jsx/loginIndex.js
index 26b4bce3e03..caa2f308911 100644
--- a/modules/login/jsx/loginIndex.js
+++ b/modules/login/jsx/loginIndex.js
@@ -15,6 +15,7 @@ import {
ButtonElement,
} from 'jsx/Form';
import SummaryStatistics from './summaryStatistics';
+import {PolicyButton} from 'jsx/PolicyButton';
/**
* Login form.
@@ -210,6 +211,16 @@ class Login extends Component {
class={'col-xs-12 col-sm-12 col-md-12 text-danger'}
/>
) : null;
+ const policy = this.state.component.requestAccount.policy;
+ const policyButton = policy ?
+