Skip to content

Commit

Permalink
Merge branch 'release/1.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
mbentz committed Apr 15, 2021
2 parents 5299607 + c65b053 commit 7ba60a8
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 34 deletions.
7 changes: 7 additions & 0 deletions Authors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# AUTHORS

_Prevent Past or Future Dates_ would not be possible without generous contributions from our authors and funders.

Christopher P Barnes, Director of the University of Florida Clinical Translational Science Institute, provides funding support for the UF CTSI REDCap team via UF CTSA Award and matching funds from the UF Office of Research.

We want to thank our developers Michael Bentz [email protected] Kyle Chesney [email protected], Taryn Stoffs [email protected], Philip Chase [email protected], and Christopher Barnes [email protected] for their contributions to the project.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Change Log
All notable changes to Prevent Past or Future Dates will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).

## [1.0.2] - 2021-04-15
### Added
Add minimum REDCap and PHP version (Michael Bentz)

### Changed
Remove eval() in js (Michael Bentz)


## [1.0.1] - 2021-04-12
### Added
- Add Zenodo DOI to README (Kyle Chesney)


## [1.0.0] - 2021-04-12
### Summary
- Initial release of Prevent Past or Future Dates
- Adds actions tags __@PREVENT-FUTUREDATE__ and __@PREVENT-PASTDATE__ that can be applied to date fields to disallow entry of dates in the future or past, respectively
- The action tags will _only_ apply to empty fields
4 changes: 2 additions & 2 deletions ExternalModule.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace PastFutureDateTags\ExternalModule;
namespace PreventPastOrFutureDates\ExternalModule;

use ExternalModules\AbstractExternalModule;

Expand Down Expand Up @@ -136,7 +136,7 @@ function redcap_every_page_top($project_id)
$this->initializeJavascriptModuleObject();
$this->tt_addToJavascriptModuleObject('preventFutureDateFields', json_encode($preventFutureDateFields));
$this->tt_addToJavascriptModuleObject('preventPastDateFields', json_encode($preventPastDateFields));
$this->includeSource(ResourceType::JS, 'js/pastFutureDateTags.js');
$this->includeSource(ResourceType::JS, 'js/preventPastOrFutureDates.js');
}
}
}
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright 2021 University of Florida

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
47 changes: 28 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
## Past Future Date Tags
This REDCap module adds actions tags __@PREVENT-FUTUREDATE__ and __@PREVENT-PASTDATE__ that can be applied to date fields-—i.e., a text field with date validation applied. The tags are mutually exclusive, applying both tags will not result in any date restrictions. To enforce todays date use the __@TODAY__ action tag instead.
# Prevent Past or Future Dates

### Scenarios
[![DOI](http://zenodo.org/badge/DOI/10.5281/zenodo.4681708.svg)](http://doi.org/10.5281/zenodo.4681708)

| | Applied Tags | Dates available in Datepicker |
| ------------- | ------------- | ------------- |
| Scenario 1 | @PREVENT-FUTUREDATE | past - today |
| Scenario 2 | @PREVENT-PASTDATE | today - future |
| Scenario 3 __NOT SUPPORTED__ | @PREVENT-FUTUREDATE && @PREVENT-PASTDATE | N/A - supplying both tags will not apply any date restrictions use __@TODAY__ instead |
This REDCap module adds actions tags __@PREVENT-FUTUREDATE__ and __@PREVENT-PASTDATE__ that can be applied to date fields - i.e., a text field with date validation applied - to disallow entry of dates in the future or past, respectively. The tags are mutually exclusive, applying both tags will not result in any date restrictions. To enforce today's date use the __@TODAY__ action tag instead.

### Expected Behavior
#### Date vs Datetime field
REDCap handles date fields and datetime fields slightly differently:
* If a datetime field fails validation and the datetimepicker is opened and loses focus, the input will be updated automatically to the closest valid date.
* If a date field fails validation and the datepicker is opened and loses focus, the input will not be updated automatically but will instead need to be updated manually.
![Prevent Future Date](img/prevent_futuredate_mdy.png)

## Prerequisites
- REDCap >= 10.0.1

#### Available dates
Dates available in the datepicker are as of the current day, it is not relative to a specific date nor when an instrument was saved. Therefore, revisiting an instrument with tagged date fields a day or more later can result in:
## Installation
- Clone this repo into to `<redcap-root>/modules/prevent_past_or_future_dates_v0.0.0`.
- Go to **Control Center > Manage External Modules** and enable _Prevent Past or Future Dates_.
- For each project you want to use this module, go to the project home page, click on **Manage External Modules** link, and then enable _Prevent Past or Future Dates_ for that project.

| | Applied Tags | Original Date Selected | (Original) Dates available in Datepicker | (+1D) Dates available in Datepciker
| ------------- | ------------- | ------------- | ------------- | ------------- |
| Scenario 1 | @PREVENT-FUTUREDATE | 01/14/2021 | past - 01/14/2021 | past - 01/15/2021 |
| Scenario 2 | @PREVENT-PASTDATE | 01/14/2021 | 01/14/2021 - future | 01/15/2021 - future |
## Expected Behavior

### Scenarios

| | Applied Tags | Dates available in Datepicker |
| ------------- | ------------- | ------------- |
| Scenario 1 | @PREVENT-FUTUREDATE | past - today |
| Scenario 2 | @PREVENT-PASTDATE | today - future |
| Scenario 3 __NOT SUPPORTED__ | @PREVENT-FUTUREDATE && @PREVENT-PASTDATE | N/A - supplying both tags will not apply any date restrictions use __@TODAY__ instead |

### Existing Data
The action tags will _only_ apply to empty fields; if data already exists in a field when the form is loaded the action tag will _not_ apply to that field. This is to prevent annoyances when revisiting forms.

### Date vs Datetime field
This module handles date fields and datetime fields slightly differently:
* If a datetime field fails validation and the datetimepicker is opened and loses focus, the input will be updated automatically to the closest valid date.
* If a date field fails validation and the datepicker is opened and loses focus, the input will not be updated automatically. A validation alert will display and the value will need to be updated manually.
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.2
22 changes: 18 additions & 4 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Past Future Date Tags",
"namespace": "PastFutureDateTags\\ExternalModule",
"description": "This module adds action tags to prevent entering past dates or future dates for date fields",
"name": "Prevent Past or Future Dates",
"namespace": "PreventPastOrFutureDates\\ExternalModule",
"description": "This module adds action tags to prevent entering past dates or future dates for date and datetime fields.",
"permissions": [
"redcap_every_page_top"
],
Expand All @@ -10,6 +10,20 @@
"name": "Michael Bentz",
"email": "[email protected]",
"institution": "University of Florida"
},
{
"name": "Kyle Chesney",
"email": "[email protected]",
"institution": "University of Florida"
},
{
"name": "Taryn Stoffs",
"email": "[email protected]",
"institution": "University of Florida"
}
]
],
"compatibility": {
"redcap-version-min": "9.5.0",
"php-version-min": "7.2.15"
}
}
116 changes: 116 additions & 0 deletions examples/pfdt_test_project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ODM xmlns="http://www.cdisc.org/ns/odm/v1.3" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:redcap="https://projectredcap.org" xsi:schemaLocation="http://www.cdisc.org/ns/odm/v1.3 schema/odm/ODM1-3-1.xsd" ODMVersion="1.3.1" FileOID="000-00-0000" FileType="Snapshot" Description="past_future_date_tags" AsOfDateTime="2021-01-21T13:02:51" CreationDateTime="2021-01-21T13:02:51" SourceSystem="REDCap" SourceSystemVersion="10.0.1">
<Study OID="Project.Pastfuturedatetags">
<GlobalVariables>
<StudyName>past_future_date_tags</StudyName>
<StudyDescription>This file contains the metadata, events, and data for REDCap project "past_future_date_tags".</StudyDescription>
<ProtocolName>past_future_date_tags</ProtocolName>
<redcap:RecordAutonumberingEnabled>1</redcap:RecordAutonumberingEnabled>
<redcap:CustomRecordLabel></redcap:CustomRecordLabel>
<redcap:SecondaryUniqueField></redcap:SecondaryUniqueField>
<redcap:SchedulingEnabled>0</redcap:SchedulingEnabled>
<redcap:SurveysEnabled>0</redcap:SurveysEnabled>
<redcap:SurveyInvitationEmailField></redcap:SurveyInvitationEmailField>
<redcap:Purpose>0</redcap:Purpose>
<redcap:PurposeOther></redcap:PurposeOther>
<redcap:ProjectNotes></redcap:ProjectNotes>
<redcap:MissingDataCodes></redcap:MissingDataCodes>
</GlobalVariables>
<MetaDataVersion OID="Metadata.Pastfuturedatetags_2021-01-21_1302" Name="past_future_date_tags" redcap:RecordIdField="record_id">
<FormDef OID="Form.test_dates" Name="Test Dates" Repeating="No" redcap:FormName="test_dates">
<ItemGroupRef ItemGroupOID="test_dates.record_id" Mandatory="No"/>
<ItemGroupRef ItemGroupOID="test_dates.test_dates_complete" Mandatory="No"/>
</FormDef>
<ItemGroupDef OID="test_dates.record_id" Name="Test Dates" Repeating="No">
<ItemRef ItemOID="record_id" Mandatory="No" redcap:Variable="record_id"/>
<ItemRef ItemOID="prevent_futuredate_mdy" Mandatory="No" redcap:Variable="prevent_futuredate_mdy"/>
<ItemRef ItemOID="prevent_futuredate_dmy" Mandatory="No" redcap:Variable="prevent_futuredate_dmy"/>
<ItemRef ItemOID="prevent_futuredate_ymd" Mandatory="No" redcap:Variable="prevent_futuredate_ymd"/>
<ItemRef ItemOID="prevent_futuredate_mdy_hm" Mandatory="No" redcap:Variable="prevent_futuredate_mdy_hm"/>
<ItemRef ItemOID="prevent_futuredate_dmy_hm" Mandatory="No" redcap:Variable="prevent_futuredate_dmy_hm"/>
<ItemRef ItemOID="prevent_futuredate_ymd_hm" Mandatory="No" redcap:Variable="prevent_futuredate_ymd_hm"/>
<ItemRef ItemOID="prevent_futuredate_mdy_hms" Mandatory="No" redcap:Variable="prevent_futuredate_mdy_hms"/>
<ItemRef ItemOID="prevent_futuredate_dmy_hms" Mandatory="No" redcap:Variable="prevent_futuredate_dmy_hms"/>
<ItemRef ItemOID="prevent_futuredate_ymd_hms" Mandatory="No" redcap:Variable="prevent_futuredate_ymd_hms"/>
<ItemRef ItemOID="prevent_pastdate_mdy" Mandatory="No" redcap:Variable="prevent_pastdate_mdy"/>
<ItemRef ItemOID="prevent_pastdate_dmy" Mandatory="No" redcap:Variable="prevent_pastdate_dmy"/>
<ItemRef ItemOID="prevent_pastdate_ymd" Mandatory="No" redcap:Variable="prevent_pastdate_ymd"/>
<ItemRef ItemOID="prevent_pastdate_mdy_hm" Mandatory="No" redcap:Variable="prevent_pastdate_mdy_hm"/>
<ItemRef ItemOID="prevent_pastdate_dmy_hm" Mandatory="No" redcap:Variable="prevent_pastdate_dmy_hm"/>
<ItemRef ItemOID="prevent_pastdate_ymd_hm" Mandatory="No" redcap:Variable="prevent_pastdate_ymd_hm"/>
<ItemRef ItemOID="prevent_pastdate_mdy_hms" Mandatory="No" redcap:Variable="prevent_pastdate_mdy_hms"/>
<ItemRef ItemOID="prevent_pastdate_dmy_hms" Mandatory="No" redcap:Variable="prevent_pastdate_dmy_hms"/>
<ItemRef ItemOID="prevent_pastdate_ymd_hms" Mandatory="No" redcap:Variable="prevent_pastdate_ymd_hms"/>
</ItemGroupDef>
<ItemGroupDef OID="test_dates.test_dates_complete" Name="Form Status" Repeating="No">
<ItemRef ItemOID="test_dates_complete" Mandatory="No" redcap:Variable="test_dates_complete"/>
</ItemGroupDef>
<ItemDef OID="record_id" Name="record_id" DataType="text" Length="999" redcap:Variable="record_id" redcap:FieldType="text">
<Question><TranslatedText>Study ID</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_mdy" Name="prevent_futuredate_mdy" DataType="date" Length="999" redcap:Variable="prevent_futuredate_mdy" redcap:FieldType="text" redcap:TextValidationType="date_mdy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_mdy</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_dmy" Name="prevent_futuredate_dmy" DataType="date" Length="999" redcap:Variable="prevent_futuredate_dmy" redcap:FieldType="text" redcap:TextValidationType="date_dmy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_dmy</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_ymd" Name="prevent_futuredate_ymd" DataType="date" Length="999" redcap:Variable="prevent_futuredate_ymd" redcap:FieldType="text" redcap:TextValidationType="date_ymd" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_ymd</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_mdy_hm" Name="prevent_futuredate_mdy_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_futuredate_mdy_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_mdy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_mdy_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_dmy_hm" Name="prevent_futuredate_dmy_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_futuredate_dmy_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_dmy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_dmy_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_ymd_hm" Name="prevent_futuredate_ymd_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_futuredate_ymd_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_ymd" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_ymd_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_mdy_hms" Name="prevent_futuredate_mdy_hms" DataType="datetime" Length="999" redcap:Variable="prevent_futuredate_mdy_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_mdy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_mdy_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_dmy_hms" Name="prevent_futuredate_dmy_hms" DataType="datetime" Length="999" redcap:Variable="prevent_futuredate_dmy_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_dmy" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_dmy_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_futuredate_ymd_hms" Name="prevent_futuredate_ymd_hms" DataType="datetime" Length="999" redcap:Variable="prevent_futuredate_ymd_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_ymd" redcap:FieldAnnotation="@PREVENT-FUTUREDATE">
<Question><TranslatedText>prevent_futuredate_ymd_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_mdy" Name="prevent_pastdate_mdy" DataType="date" Length="999" redcap:Variable="prevent_pastdate_mdy" redcap:FieldType="text" redcap:TextValidationType="date_mdy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_mdy</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_dmy" Name="prevent_pastdate_dmy" DataType="date" Length="999" redcap:Variable="prevent_pastdate_dmy" redcap:FieldType="text" redcap:TextValidationType="date_dmy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_dmy</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_ymd" Name="prevent_pastdate_ymd" DataType="date" Length="999" redcap:Variable="prevent_pastdate_ymd" redcap:FieldType="text" redcap:TextValidationType="date_ymd" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_ymd</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_mdy_hm" Name="prevent_pastdate_mdy_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_pastdate_mdy_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_mdy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_mdy_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_dmy_hm" Name="prevent_pastdate_dmy_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_pastdate_dmy_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_dmy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_dmy_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_ymd_hm" Name="prevent_pastdate_ymd_hm" DataType="partialDatetime" Length="999" redcap:Variable="prevent_pastdate_ymd_hm" redcap:FieldType="text" redcap:TextValidationType="datetime_ymd" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_ymd_HM</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_mdy_hms" Name="prevent_pastdate_mdy_hms" DataType="datetime" Length="999" redcap:Variable="prevent_pastdate_mdy_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_mdy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_mdy_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_dmy_hms" Name="prevent_pastdate_dmy_hms" DataType="datetime" Length="999" redcap:Variable="prevent_pastdate_dmy_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_dmy" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_dmy_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="prevent_pastdate_ymd_hms" Name="prevent_pastdate_ymd_hms" DataType="datetime" Length="999" redcap:Variable="prevent_pastdate_ymd_hms" redcap:FieldType="text" redcap:TextValidationType="datetime_seconds_ymd" redcap:FieldAnnotation="@PREVENT-PASTDATE">
<Question><TranslatedText>prevent_pastdate_ymd_HMS</TranslatedText></Question>
</ItemDef>
<ItemDef OID="test_dates_complete" Name="test_dates_complete" DataType="text" Length="1" redcap:Variable="test_dates_complete" redcap:FieldType="select" redcap:SectionHeader="Form Status">
<Question><TranslatedText>Complete?</TranslatedText></Question>
<CodeListRef CodeListOID="test_dates_complete.choices"/>
</ItemDef>
<CodeList OID="test_dates_complete.choices" Name="test_dates_complete" DataType="text" redcap:Variable="test_dates_complete">
<CodeListItem CodedValue="0"><Decode><TranslatedText>Incomplete</TranslatedText></Decode></CodeListItem>
<CodeListItem CodedValue="1"><Decode><TranslatedText>Unverified</TranslatedText></Decode></CodeListItem>
<CodeListItem CodedValue="2"><Decode><TranslatedText>Complete</TranslatedText></Decode></CodeListItem>
</CodeList>
</MetaDataVersion>
</Study>
</ODM>
Binary file added img/prevent_futuredate_mdy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions js/addActionTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ $(document).ready(function () {

$('body').on('dialogopen', function (event, ui) {
let $popup = $(event.target);
let module = ExternalModules['PastFutureDateTags'].ExternalModule;
let module = ExternalModules['PreventPastOrFutureDates'].ExternalModule;
let futureDateTag = module.tt('futureDateTag');
let pastDateTag = module.tt('pastDateTag');

Expand Down Expand Up @@ -59,4 +59,4 @@ $(document).ready(function () {
$new_action_tag.insertBefore($default_action_tag);
}

});
});
Loading

0 comments on commit 7ba60a8

Please sign in to comment.