From e60f493ba75ba8fa6306998bc3369c91408835b2 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:29:46 -0400 Subject: [PATCH 01/28] Add repeating instrument methods --- src/REDCap.jl | 2 +- .../repeating_instruments_and_events.jl | 26 ++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index 77df849..b47f042 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -19,7 +19,7 @@ include("api_methods/metadata.jl") include("api_methods/projects.jl") include("api_methods/records.jl") include("api_methods/redcap.jl") -#include("api_methods/repeating_instruments_and_events.jl") +include("api_methods/repeating_instruments_and_events.jl") #include("api_methods/reports.jl") #include("api_methods/surveys.jl") include("api_methods/users.jl") diff --git a/src/api_methods/repeating_instruments_and_events.jl b/src/api_methods/repeating_instruments_and_events.jl index 6764862..e7c9c1b 100644 --- a/src/api_methods/repeating_instruments_and_events.jl +++ b/src/api_methods/repeating_instruments_and_events.jl @@ -1,16 +1,34 @@ export export_repeating_instruments_and_events, import_repeating_instruments_and_events -function export_repeating_instruments_and_events(;format=:xml) +function export_repeating_instruments_and_events(; + url::redcap_url_parameter=get_url(), + token::redcap_super_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + ) + REDCap.request( - content=REDCap_content(:repeatingFormsEvents), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:repeatingFormsEvents), format=REDCap_format(format), ) end -function import_repeating_instruments_and_events(;format=:xml,data=nothing,returnFormat=nothing) +function import_repeating_instruments_and_events(; + url::redcap_url_parameter=get_url(), + token::redcap_super_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + data::redcap_data_parameter, #TODO: the docs mention a super API token may be used here...? + #TODO: data parameter is essential to distringuish from an export + #TODO: does is make sense to define one method in terms of the other? + ) + REDCap.request( - content=REDCap_content(:repeatingFormsEvents), + content=REDCap_content(:repeatingFormsEvents), + url=URI(url), + token=REDCap_token(token), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), ) From d51502400084d06312bafeaaac5caeec9775c0e5 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:55:29 -0400 Subject: [PATCH 02/28] Add file methods --- src/REDCap.jl | 2 +- src/api_methods/files.jl | 32 ++++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index b47f042..67830be 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -11,7 +11,7 @@ include("utils.jl") #include("api_methods/data_access_groups.jl") #include("api_methods/events.jl") include("api_methods/field_names.jl") -#include("api_methods/files.jl") +include("api_methods/files.jl") #include("api_methods/file_repository.jl") #include("api_methods/instruments.jl") include("api_methods/logging.jl") diff --git a/src/api_methods/files.jl b/src/api_methods/files.jl index 944ef7b..c543dee 100644 --- a/src/api_methods/files.jl +++ b/src/api_methods/files.jl @@ -1,8 +1,15 @@ export delete_file, export_file, import_file -function delete_file(;record=nothing,field=nothing,event=nothing,repeat_instance=nothing,returnFormat=:xml) +function delete_file(; + record=nothing, + field=nothing, + event=nothing, + repeat_instance=nothing, + returnFormat=nothing + ) + REDCap.request(; - content=REDCap_content(:file), + content=REDCap_content(:file), action=:delete, record=record, field=field, @@ -12,9 +19,15 @@ function delete_file(;record=nothing,field=nothing,event=nothing,repeat_instance ) end -function export_file(;record=nothing,field=nothing,event=nothing,repeat_instance=nothing,returnFormat=:xml) +function export_file(; + record=nothing, + field=nothing, + event=nothing, + repeat_instance=nothing, + returnFormat=nothing) + REDCap.request(; - content=REDCap_content(:file), + content=REDCap_content(:file), action=:export, record=record, field=field, @@ -24,9 +37,16 @@ function export_file(;record=nothing,field=nothing,event=nothing,repeat_instance ) end -function import_file(;record=nothing,field=nothing,event=nothing,repeat_instance=nothing,file=nothing,returnFormat=:xml) +function import_file(; + record=nothing, + field=nothing, + event=nothing, + repeat_instance=nothing, + file=nothing, + returnFormat=nothing) + REDCap.request(; - content=REDCap_content(:file), + content=REDCap_content(:file), action=:import, record=record, field=field, From feae17a17ea1437cdad6d72b03be055bf409aba6 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:03:31 -0400 Subject: [PATCH 03/28] Add REDCap_action type --- src/api_methods/arms.jl | 4 ++-- src/api_methods/data_access_groups.jl | 6 +++--- src/api_methods/events.jl | 4 ++-- src/api_methods/file_repository.jl | 10 +++++----- src/api_methods/files.jl | 6 +++--- src/api_methods/records.jl | 4 ++-- src/api_methods/user_roles.jl | 2 +- src/api_methods/users.jl | 2 +- src/types.jl | 12 ++++++++++-- 9 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index a391bbd..a55123b 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -5,7 +5,7 @@ export delete_arms, function delete_arms(;arms=nothing) REDCap.request(; content=REDCap_content(:arm), - action=:import, + action=REDCap_action(:import), arms=arms, ) end @@ -23,7 +23,7 @@ function import_arms(;format=:xml,data=nothing,override=0,returnFormat=nothing) REDCap.request(; content=REDCap_content(:arm), override=override, - action=:import, + action=REDCap_action(:import), format=REDCap_format(format), data=data, returnFormat=REDCap_format(returnFormat), diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index a0c4a1a..b95e3b3 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -8,7 +8,7 @@ export delete_DAGs, function delete_DAGs(;dags=nothing) REDCap.request(; content=REDCap_content(:dag), - action=:delete, + action=REDCap_action(:delete), dags=dags, ) end @@ -31,7 +31,7 @@ end function import_DAGs(;format=:xml,data=nothing,returnFormat=nothing) REDCap.request(; content=REDCap_content(:dag), - action=:import, + action=REDCap_action(:import), format=REDCap_format(format), data=data, returnFormat=REDCap_format(returnFormat), @@ -50,7 +50,7 @@ end function switch_DAG(;dag=nothing) REDCap.request(; content=REDCap_content(:dag), - action=:switch, + action=REDCap_action(:switch), dag=dag, ) end diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index c7dfb11..0aa1a44 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -5,7 +5,7 @@ export delete_events, function delete_events(;events=nothing) REDCap.request(; content=REDCap_content(:event), - action=:import, + action=REDCap_action(:import), events=events, ) end @@ -22,7 +22,7 @@ end function import_events(;format=:xml,data=nothing,override=0,returnFormat=nothing) REDCap.request(; content=REDCap_content(:event), - action=:import, + action=REDCap_action(:import), override=override, format=REDCap_format(format), data=data, diff --git a/src/api_methods/file_repository.jl b/src/api_methods/file_repository.jl index a207456..39948a7 100644 --- a/src/api_methods/file_repository.jl +++ b/src/api_methods/file_repository.jl @@ -7,7 +7,7 @@ export create_folder, function create_folder(;name=nothing,format=:xml,folder_id=nothing,dag_id=nothing,role_id=nothing,returnFormat=:xml) REDCap.request(; content=REDCap_content(:fileRepository), - action=:createFolder, + action=REDCap_action(:createFolder), name=name, format=REDCap_format(format), folder_id=folder_id, @@ -20,7 +20,7 @@ end function delete_file_from_file_repository(;name=nothing,format=:xml,doc_id=nothing,returnFormat=:xml) REDCap.request(; content=REDCap_content(:fileRepository), - action=:delete, + action=REDCap_action(:delete), doc_id=doc_id, returnFormat=REDCap_format(returnFormat), ) @@ -29,7 +29,7 @@ end function export_file_from_file_repository(;name=nothing,format=:xml,doc_id=nothing,returnFormat=:xml) REDCap.request(; content=REDCap_content(:fileRepository), - action=:export, + action=REDCap_action(:export), doc_id=doc_id, returnFormat=REDCap_format(returnFormat), ) @@ -38,7 +38,7 @@ end function export_list_of_folders(;name=nothing,format=:xml,folder_id=nothing,returnFormat=:xml) REDCap.request(; content=REDCap_content(:fileRepository), - action=:list, + action=REDCap_action(:list), name=name, format=REDCap_format(format), folder_id=folder_id, @@ -49,7 +49,7 @@ end function import_file_from_file_repository(;name=nothing,format=:xml,file=nothing,folder_id=nothing,returnFormat=:xml) REDCap.request(; content=REDCap_content(:fileRepository), - action=:import, + action=REDCap_action(:import), file=file, folder_id=folder_id, returnFormat=REDCap_format(returnFormat), diff --git a/src/api_methods/files.jl b/src/api_methods/files.jl index c543dee..33b5c49 100644 --- a/src/api_methods/files.jl +++ b/src/api_methods/files.jl @@ -10,7 +10,7 @@ function delete_file(; REDCap.request(; content=REDCap_content(:file), - action=:delete, + action=REDCap_action(:delete), record=record, field=field, event=event, @@ -28,7 +28,7 @@ function export_file(; REDCap.request(; content=REDCap_content(:file), - action=:export, + action=REDCap_action(:export), record=record, field=field, event=event, @@ -47,7 +47,7 @@ function import_file(; REDCap.request(; content=REDCap_content(:file), - action=:import, + action=REDCap_action(:import), record=record, field=field, event=event, diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index 463ab69..91c8ddb 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -19,7 +19,7 @@ function delete_records(; url=URI(url), token=REDCap_token(token), content=REDCap_content(:record), - action=:delete, + action=REDCap_action(:delete), records=records, arm=arm, instrument=instrument, @@ -134,7 +134,7 @@ function rename_record(; url=URI(url), token=REDCap_token(token), content=REDCap_content(:record), - action=:rename, + action=REDCap_action(:rename), record=record, new_record_name=new_record_name, arm=arm, diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index 1c8d82c..6c4128b 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -14,7 +14,7 @@ function delete_user_roles(; url=URI(url), token=REDCap_token(token), content=REDCap_content(:userRole), - action=:delete, + action=REDCap_action(:delete), roles=roles, ) end diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index 02a7381..8bfdd45 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -11,7 +11,7 @@ function delete_users(; url=URI(url), token=REDCap_token(token), content=REDCap_content(:user), - action=:delete, + action=REDCap_action(:delete), users=users, ) end diff --git a/src/types.jl b/src/types.jl index ba82afc..8e0e0e9 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,3 +1,11 @@ +struct REDCap_action + id::Symbol + REDCap_action(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid action parameter")) +end +Base.display(x::REDCap_action) = Base.display(x.id) +Base.string(x::REDCap_action) = Base.string(x.id) +Base.convert(String,x::REDCap_action) = string(x) + struct REDCap_content id::Symbol REDCap_content(id) = id ∈ [:arm,:dag,:userDagMapping,:event,:exportFieldNames,:fileRepository,:file,:formEventMapping,:instrument,:pdf,:log,:metadata,:project,:project_settings,:project_xml,:record,:generateNextRecordName,:record,:version,:repeatingFormsEvents,:report,:surveyLink,:participantList,:surveyQueueLink,:userRole,:userRoleMapping,:user,] ? new(id) : throw(ArgumentError("Invalid content parameter")) @@ -10,7 +18,7 @@ const REDCap_url = URIs.URI const redcap_url_parameter = Union{REDCap_url,String} const redcap_token_parameter = String const redcap_super_token_parameter = String -const redcap_action_parameter = Union{Symbol, Nothing} +#const redcap_action_parameter = Union{Symbol, Nothing} const redcap_data_parameter = Any #const redcap_data_parameter = Union{IOStream, Dict, String, Nothing} #TODO: this can be nothing in REDCap.request(), but must be mandatory wherever it is a method parameter. Otherwise, it changes the method behavior, which would contradict the guarantee of the function name const redcap_filterLogic_parameter = Union{String, Nothing} @@ -25,7 +33,7 @@ const redcap_symbol = Union{Symbol, Nothing} const redcap_timestamp = Union{DateTime, Nothing} #TODO: YYYY-MM-DD HH:MM redcap_generic_parameter = Union{ - redcap_action_parameter, + #redcap_action_parameter, redcap_data_parameter, redcap_filterLogic_parameter, redcap_odm_parameter, From 93199cdc0d125619d18705728b3149c3a1e919a3 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:06:45 -0400 Subject: [PATCH 04/28] Add report method --- src/REDCap.jl | 2 +- src/api_methods/reports.jl | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index 67830be..a153a41 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -20,7 +20,7 @@ include("api_methods/projects.jl") include("api_methods/records.jl") include("api_methods/redcap.jl") include("api_methods/repeating_instruments_and_events.jl") -#include("api_methods/reports.jl") +include("api_methods/reports.jl") #include("api_methods/surveys.jl") include("api_methods/users.jl") include("api_methods/user_roles.jl") diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index ebc4a88..0a00447 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -1,10 +1,20 @@ export export_reports -function export_reports(;report_id=nothing,format=:xml,returnFormat=nothing,rawOrLabel="raw",rawOrLabelHeaders="raw",exportCheckboxLabel=false,csvDelimiter=',',decimalCharacter=".") +function export_reports(; + report_id=nothing, + format=nothing, + returnFormat=nothing, + rawOrLabel=nothing, + rawOrLabelHeaders=nothing, + exportCheckboxLabel=nothing, + csvDelimiter=nothing, + decimalCharacter=nothing, + ) + REDCap.request( - content=REDCap_content(:report), + content=REDCap_content(:report), report_id=report_id, - format=REDCap_format(format), # format can include odm + format=REDCap_format(format), #TODO: format can include odm returnFormat=REDCap_format(returnFormat), rawOrLabel=rawOrLabel, rawOrLabelHeaders=rawOrLabelHeaders, From a113aa6f657af8c1e090355b157d872939a1ee26 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:15:50 -0400 Subject: [PATCH 05/28] Update arm methods --- src/REDCap.jl | 2 +- src/api_methods/arms.jl | 40 +++++++++++++++++++++++++++++++------- src/api_methods/files.jl | 20 ++++++++++++++++--- src/api_methods/reports.jl | 8 ++++++-- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index a153a41..35df947 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -7,7 +7,7 @@ using URIs include("types.jl") include("utils.jl") -#include("api_methods/arms.jl") +include("api_methods/arms.jl") #include("api_methods/data_access_groups.jl") #include("api_methods/events.jl") include("api_methods/field_names.jl") diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index a55123b..1854e46 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -2,26 +2,52 @@ export delete_arms, export_arms, import_arms -function delete_arms(;arms=nothing) +function delete_arms(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + arms=nothing, + ) + REDCap.request(; - content=REDCap_content(:arm), - action=REDCap_action(:import), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:arm), + action=REDCap_action(:import), arms=arms, ) end -function export_arms(;format=:xml,arms=nothing,returnFormat=nothing) +function export_arms(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + arms=nothing, + ) + REDCap.request(; - content=REDCap_content(:arm), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:arm), format=REDCap_format(format), arms=arms, returnFormat=REDCap_format(returnFormat), ) end -function import_arms(;format=:xml,data=nothing,override=0,returnFormat=nothing) +function import_arms(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + data::redcap_data_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + override=0, + ) + REDCap.request(; - content=REDCap_content(:arm), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:arm), override=override, action=REDCap_action(:import), format=REDCap_format(format), diff --git a/src/api_methods/files.jl b/src/api_methods/files.jl index 33b5c49..4049b2c 100644 --- a/src/api_methods/files.jl +++ b/src/api_methods/files.jl @@ -1,14 +1,18 @@ export delete_file, export_file, import_file function delete_file(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, record=nothing, field=nothing, event=nothing, repeat_instance=nothing, - returnFormat=nothing ) REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:delete), record=record, @@ -20,13 +24,18 @@ function delete_file(; end function export_file(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, record=nothing, field=nothing, event=nothing, repeat_instance=nothing, - returnFormat=nothing) + ) REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:export), record=record, @@ -38,14 +47,19 @@ function export_file(; end function import_file(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, record=nothing, field=nothing, event=nothing, repeat_instance=nothing, file=nothing, - returnFormat=nothing) + ) REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:import), record=record, diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index 0a00447..453de01 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -1,9 +1,11 @@ export export_reports function export_reports(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + fields::redcap_array=nothing, report_id=nothing, - format=nothing, - returnFormat=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, @@ -12,6 +14,8 @@ function export_reports(; ) REDCap.request( + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:report), report_id=report_id, format=REDCap_format(format), #TODO: format can include odm From 705bc095f2c31b097d73a67e007e5d1ce20eb42c Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:21:40 -0400 Subject: [PATCH 06/28] Update survey methods --- src/REDCap.jl | 2 +- src/api_methods/surveys.jl | 42 ++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index 35df947..8d1eebb 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -21,7 +21,7 @@ include("api_methods/records.jl") include("api_methods/redcap.jl") include("api_methods/repeating_instruments_and_events.jl") include("api_methods/reports.jl") -#include("api_methods/surveys.jl") +include("api_methods/surveys.jl") include("api_methods/users.jl") include("api_methods/user_roles.jl") diff --git a/src/api_methods/surveys.jl b/src/api_methods/surveys.jl index 51db2d7..19b6326 100644 --- a/src/api_methods/surveys.jl +++ b/src/api_methods/surveys.jl @@ -3,8 +3,19 @@ export_survey_participants, export_survey_queue_link, export_survey_return_code -function export_survey_link(;record=nothing,instrument=nothing,event=nothing,repeat_instance=nothing,returnFormat=:xml) +function export_survey_link(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, + record=nothing, + instrument=nothing, + event=nothing, + repeat_instance=nothing, + ) + REDCap.request( + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:surveyLink), record=record, instrument=instrument, @@ -14,8 +25,19 @@ function export_survey_link(;record=nothing,instrument=nothing,event=nothing,rep ) end -function export_survey_participants(;instrument=nothing,event=nothing,repeat_instance=nothing,format=:xml,returnFormat=nothing) +function export_survey_participants(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + instrument=nothing, + event=nothing, + repeat_instance=nothing, + ) + REDCap.request( + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:participantList), instrument=instrument, event=event, @@ -27,14 +49,26 @@ end function export_survey_queue_link(;record=nothing,returnFormat=:xml) REDCap.request( - content=REDCap_content(:surveyQueueLink), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:surveyQueueLink), record=record, returnFormat=REDCap_format(returnFormat), ) end -function export_survey_return_code(;record=nothing,instrument=nothing,event=nothing,repeat_instance=nothing,returnFormat=:xml) +function export_survey_return_code(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, + record=nothing, + instrument=nothing, + event=nothing, + repeat_instance=nothing, +) REDCap.request( + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:surveyLink), record=record, instrument=instrument, From a99e409056d2933040e814b5d4ed97d168d3ba2d Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:11:32 -0400 Subject: [PATCH 07/28] Add DAG methods --- src/REDCap.jl | 2 +- src/api_methods/data_access_groups.jl | 58 +++++++++++++++++++++++---- src/api_methods/projects.jl | 5 ++- test/runtests.jl | 7 ++++ 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index 8d1eebb..101967e 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -8,7 +8,7 @@ using URIs include("types.jl") include("utils.jl") include("api_methods/arms.jl") -#include("api_methods/data_access_groups.jl") +include("api_methods/data_access_groups.jl") #include("api_methods/events.jl") include("api_methods/field_names.jl") include("api_methods/files.jl") diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index b95e3b3..c845b04 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -5,31 +5,61 @@ export delete_DAGs, import_user_DAG_assignment, switch_DAG -function delete_DAGs(;dags=nothing) +function delete_DAGs(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + dags=nothing) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:delete), dags=dags, ) end -function export_DAGs(;format=:xml,returnFormat=nothing) +function export_DAGs(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + #TODO: This is one of those ones that only take a format parameter + ) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:dag), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), ) end -function export_user_DAG_assignment(;format=:xml) +function export_user_DAG_assignment(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + ) + REDCap.request(; - content=REDCap_content(:userDagMapping), + url=URI(url), + token=REDCap_token(token), + content=REDCap_content(:userDagMapping), format=REDCap_format(format), ) end -function import_DAGs(;format=:xml,data=nothing,returnFormat=nothing) +function import_DAGs(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + data::redcap_data_parameter=nothing, #TODO: It would be great to support a Dict here + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + ) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:import), format=REDCap_format(format), @@ -38,8 +68,17 @@ function import_DAGs(;format=:xml,data=nothing,returnFormat=nothing) ) end -function import_user_DAG_assignment(;format=:xml,data=nothing,returnFormat=nothing) +function import_user_DAG_assignment(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + data::redcap_data_parameter=nothing, + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + ) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:userDagMapping), format=REDCap_format(format), data=data, @@ -47,8 +86,13 @@ function import_user_DAG_assignment(;format=:xml,data=nothing,returnFormat=nothi ) end -function switch_DAG(;dag=nothing) +function switch_DAG(; + data::redcap_data_parameter=nothing, + url::redcap_url_parameter=get_url(), + dag=nothing) REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:switch), dag=dag, diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 074bb53..d8710ef 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -4,7 +4,7 @@ export create_project, import_project_info function create_project(; - data::redcap_data_parameter=nothing, + data::redcap_data_parameter, url::redcap_url_parameter=get_url(), token::redcap_super_token_parameter=get_token(), format::redcap_format_parameter=nothing, @@ -13,11 +13,14 @@ function create_project(; if isa(data,Dict) @assert Symbol.(keys(data)) ⊆ [:project_title, :purpose, :purpose_other, :project_notes, :is_longitudinal, :surveys_enabled, :record_autonumbering_enabled,] + #TODO: check when data isn't a Dict? + if [:project_title, :purpose] ⊈ Symbol.(keys(data)); throw(ArgumentError("The data field must include a project title and purpose")) end data="[$(JSON.json(data))]" #TODO: best way to avoid type change? # maybe function to map (Dict,String) to (String,String) format=:json end + REDCap.request(; content=REDCap_content(:project), format=REDCap_format(format), diff --git a/test/runtests.jl b/test/runtests.jl index 1a656a7..f40d9e3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -33,6 +33,13 @@ begin @assert "1" == import_project_info(token=token,data=Dict(:project_title=>"$(now())",:purpose=>0)) export_logging(token=token, format=:json) |>JSON.parse |> DataFrame + #TODO: for CSV inputs, use triple quotes, and add a comma at the end if the last inner character is also a quote + # Can this always be done, or only when the last column is blank? + import_DAGs(token=t,format=:csv,data="""data_access_group_name,unique_group_name + "CA Site", + "FL Site", + "New Site",""") + import_users(token=token,format=:xml,data=""" From 6b7697435c3944b0a82d65015f1abefc75f453a2 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:58:57 -0400 Subject: [PATCH 08/28] Update event methods --- src/REDCap.jl | 2 +- src/api_methods/events.jl | 40 ++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index 101967e..a8e5c58 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -9,7 +9,7 @@ include("types.jl") include("utils.jl") include("api_methods/arms.jl") include("api_methods/data_access_groups.jl") -#include("api_methods/events.jl") +include("api_methods/events.jl") include("api_methods/field_names.jl") include("api_methods/files.jl") #include("api_methods/file_repository.jl") diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index 0aa1a44..8b6f9fd 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -2,31 +2,57 @@ export delete_events, import_events, export_events -function delete_events(;events=nothing) +function delete_events(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + events=nothing, + ) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), content=REDCap_content(:event), action=REDCap_action(:import), events=events, ) end -function export_events(;format=:xml,arms=nothing,returnFormat=nothing) +function export_events(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + arms=nothing, + ) + REDCap.request(; - content=REDCap_content(:event), + url=URI(url), + token=REDCap_token(token), format=REDCap_format(format), - arms=arms, returnFormat=REDCap_format(returnFormat), + content=REDCap_content(:event), + arms=arms, ) end -function import_events(;format=:xml,data=nothing,override=0,returnFormat=nothing) +function import_events(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + data=nothing, + override=0, + ) + REDCap.request(; + url=URI(url), + token=REDCap_token(token), + format=REDCap_format(format), + returnFormat=REDCap_format(returnFormat), content=REDCap_content(:event), action=REDCap_action(:import), override=override, - format=REDCap_format(format), data=data, - returnFormat=REDCap_format(returnFormat), ) end From 6f61c0537d359d07150f627fe93725b08234b16a Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Thu, 22 Aug 2024 19:41:51 -0400 Subject: [PATCH 09/28] Log HTTP status code --- src/utils.jl | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 7f645d3..0340aff 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -9,15 +9,31 @@ function request(; html_request_body["token"] = token html_request_body["content"] = "$content" - return HTTP.post( + response = HTTP.post( URI(url); #get_valid_url(); body=html_request_body, require_ssl_verification=true, #verbose = 3, status_exception=false, - ).body |> String + ) + #HTTP.iserror(r) + + status_codes_message = Dict( + 200 => "OK: Success!", + 400 => "Bad Request: The request was invalid.", + 401 => "Unauthorized: API token was missing or incorrect.", + 403 => "Forbidden: You do not have permissions to use the API.", + 404 => "Not Found: The URI you requested is invalid or the resource does not exist.", + 406 => "Not Acceptable: The data being imported was formatted incorrectly.", + 500 => "Internal Server Error: The server encountered an error processing your request.", + 501 => "Not Implemented: The requested method is not implemented.", + ) + + @info("HTTP response $(response.status), $(get(status_codes_message,response.status,"Unknown"))") + + return response.body|> String end function assemble_html_body(;kwargs...) From a3d4367e2ed0d8598bf8c8610d7f896283a87853 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:05:12 -0400 Subject: [PATCH 10/28] Assert url format --- src/api_methods/arms.jl | 6 +++--- src/api_methods/data_access_groups.jl | 12 ++++++------ src/api_methods/events.jl | 6 +++--- src/api_methods/field_names.jl | 2 +- src/api_methods/files.jl | 6 +++--- src/api_methods/logging.jl | 2 +- src/api_methods/metadata.jl | 4 ++-- src/api_methods/projects.jl | 8 ++++---- src/api_methods/records.jl | 10 +++++----- src/api_methods/redcap.jl | 2 +- src/api_methods/repeating_instruments_and_events.jl | 4 ++-- src/api_methods/reports.jl | 2 +- src/api_methods/surveys.jl | 8 ++++---- src/api_methods/user_roles.jl | 10 +++++----- src/api_methods/users.jl | 6 +++--- src/types.jl | 6 ++++-- src/utils.jl | 2 +- 17 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index 1854e46..20afde5 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -9,7 +9,7 @@ function delete_arms(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:arm), action=REDCap_action(:import), @@ -26,7 +26,7 @@ function export_arms(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:arm), format=REDCap_format(format), @@ -45,7 +45,7 @@ function import_arms(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:arm), override=override, diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index c845b04..ae6ee02 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -11,7 +11,7 @@ function delete_DAGs(; dags=nothing) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:delete), @@ -27,7 +27,7 @@ function export_DAGs(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:dag), format=REDCap_format(format), @@ -42,7 +42,7 @@ function export_user_DAG_assignment(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userDagMapping), format=REDCap_format(format), @@ -58,7 +58,7 @@ function import_DAGs(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:import), @@ -77,7 +77,7 @@ function import_user_DAG_assignment(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userDagMapping), format=REDCap_format(format), @@ -91,7 +91,7 @@ function switch_DAG(; url::redcap_url_parameter=get_url(), dag=nothing) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:dag), action=REDCap_action(:switch), diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index 8b6f9fd..28dc5b1 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -9,7 +9,7 @@ function delete_events(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:event), action=REDCap_action(:import), @@ -26,7 +26,7 @@ function export_events(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), @@ -45,7 +45,7 @@ function import_events(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), diff --git a/src/api_methods/field_names.jl b/src/api_methods/field_names.jl index 4734086..af9bd4c 100644 --- a/src/api_methods/field_names.jl +++ b/src/api_methods/field_names.jl @@ -9,7 +9,7 @@ function export_list_of_export_field_names(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:exportFieldNames), format=REDCap_format(format), diff --git a/src/api_methods/files.jl b/src/api_methods/files.jl index 4049b2c..47d4191 100644 --- a/src/api_methods/files.jl +++ b/src/api_methods/files.jl @@ -11,7 +11,7 @@ function delete_file(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:delete), @@ -34,7 +34,7 @@ function export_file(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:export), @@ -58,7 +58,7 @@ function import_file(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:file), action=REDCap_action(:import), diff --git a/src/api_methods/logging.jl b/src/api_methods/logging.jl index 67ba5bb..c32cbc2 100644 --- a/src/api_methods/logging.jl +++ b/src/api_methods/logging.jl @@ -13,7 +13,7 @@ function export_logging(; endTime::redcap_timestamp=nothing, ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:log), format=REDCap_format(format), diff --git a/src/api_methods/metadata.jl b/src/api_methods/metadata.jl index 1757ae8..1e1865a 100644 --- a/src/api_methods/metadata.jl +++ b/src/api_methods/metadata.jl @@ -10,7 +10,7 @@ function export_metadata(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:metadata), format=REDCap_format(format), @@ -29,7 +29,7 @@ function import_metadata(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:metadata), format=REDCap_format(format), diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index d8710ef..3f2581d 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -26,7 +26,7 @@ function create_project(; format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), data=data, - url=URI(url), + url=REDCap_url(url), token=REDCap_super_token(token), odm=odm, ) @@ -40,7 +40,7 @@ function export_project_info(; REDCap.request(; content=REDCap_content(:project), - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), returnFormat=REDCap_format(returnFormat), ) @@ -61,7 +61,7 @@ function export_project_XML(; exportFiles::redcap_bool=nothing, ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:project_xml), returnMetadataOnly=returnMetadataOnly, @@ -87,7 +87,7 @@ function import_project_info(;name=nothing,format=nothing,data, end REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:project_settings), format=REDCap_format(format), diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index 91c8ddb..d9e94da 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -16,7 +16,7 @@ function delete_records(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), action=REDCap_action(:delete), @@ -53,7 +53,7 @@ function export_records(; ) REDCap.request( data=data, - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), format=REDCap_format(format), #allows odm, unlike most other format args @@ -84,7 +84,7 @@ function generate_next_record_name( REDCap.request( data=data, - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:generateNextRecordName), ) @@ -107,7 +107,7 @@ function import_records(; REDCap.request( data=data, - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), format=REDCap_format(format), #allows odm, unlike most other format args @@ -131,7 +131,7 @@ function rename_record(; REDCap.request( data=data, - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), action=REDCap_action(:rename), diff --git a/src/api_methods/redcap.jl b/src/api_methods/redcap.jl index 7998bac..05965de 100644 --- a/src/api_methods/redcap.jl +++ b/src/api_methods/redcap.jl @@ -6,7 +6,7 @@ function export_version(; ) REDCap.request(; - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:version), ) diff --git a/src/api_methods/repeating_instruments_and_events.jl b/src/api_methods/repeating_instruments_and_events.jl index e7c9c1b..184ee17 100644 --- a/src/api_methods/repeating_instruments_and_events.jl +++ b/src/api_methods/repeating_instruments_and_events.jl @@ -8,7 +8,7 @@ function export_repeating_instruments_and_events(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:repeatingFormsEvents), format=REDCap_format(format), @@ -27,7 +27,7 @@ function import_repeating_instruments_and_events(; REDCap.request( content=REDCap_content(:repeatingFormsEvents), - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index 453de01..293ff14 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -14,7 +14,7 @@ function export_reports(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:report), report_id=report_id, diff --git a/src/api_methods/surveys.jl b/src/api_methods/surveys.jl index 19b6326..36c7e13 100644 --- a/src/api_methods/surveys.jl +++ b/src/api_methods/surveys.jl @@ -14,7 +14,7 @@ function export_survey_link(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:surveyLink), record=record, @@ -36,7 +36,7 @@ function export_survey_participants(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:participantList), instrument=instrument, @@ -49,7 +49,7 @@ end function export_survey_queue_link(;record=nothing,returnFormat=:xml) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:surveyQueueLink), record=record, @@ -67,7 +67,7 @@ function export_survey_return_code(; repeat_instance=nothing, ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:surveyLink), record=record, diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index 6c4128b..8b0ff0c 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -11,7 +11,7 @@ function delete_user_roles(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userRole), action=REDCap_action(:delete), @@ -28,7 +28,7 @@ function export_user_roles(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userRole), format=REDCap_format(format), @@ -45,7 +45,7 @@ function import_user_roles(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userRole), format=REDCap_format(format), @@ -63,7 +63,7 @@ function export_user_role_assignments(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userRoleMapping), format=REDCap_format(format), @@ -80,7 +80,7 @@ function import_user_role_assignments(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:userRoleMapping), format=REDCap_format(format), diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index 8bfdd45..d53f1d0 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -8,7 +8,7 @@ function delete_users(; users::redcap_array=nothing, ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:user), action=REDCap_action(:delete), @@ -24,7 +24,7 @@ function export_users(; ) REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:user), format=REDCap_format(format), @@ -47,7 +47,7 @@ function import_users(; end REDCap.request( - url=URI(url), + url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:user), format=REDCap_format(format), diff --git a/src/types.jl b/src/types.jl index 8e0e0e9..627270e 100644 --- a/src/types.jl +++ b/src/types.jl @@ -14,8 +14,10 @@ Base.display(x::REDCap_content) = Base.display(x.id) Base.string(x::REDCap_content) = Base.string(x.id) Base.convert(String,x::REDCap_content) = string(x) -const REDCap_url = URIs.URI -const redcap_url_parameter = Union{REDCap_url,String} +const redcap_url_parameter = String +#TODO: help users fix formatting errors - I left out the final slash and had trouble debugging +REDCap_url(x::redcap_url_parameter) = occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) + const redcap_token_parameter = String const redcap_super_token_parameter = String #const redcap_action_parameter = Union{Symbol, Nothing} diff --git a/src/utils.jl b/src/utils.jl index 0340aff..e95bae0 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,5 +1,5 @@ function request(; - url::REDCap_url, + url::URI, token::Union{REDCap_token, REDCap_super_token}, content::REDCap_content, kwargs...) From 414787c7a75fe47852d1af7d159f7d9d9b26e92f Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:49:24 -0400 Subject: [PATCH 11/28] Move HTTP status logs to debug --- src/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index e95bae0..d467b11 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -31,7 +31,7 @@ function request(; 501 => "Not Implemented: The requested method is not implemented.", ) - @info("HTTP response $(response.status), $(get(status_codes_message,response.status,"Unknown"))") + @debug("HTTP response $(response.status), $(get(status_codes_message,response.status,"Unknown"))") return response.body|> String end From 3dab2fc86beda3c77736c2d525b074c73792d9eb Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:50:26 -0400 Subject: [PATCH 12/28] Update instrument methods --- src/REDCap.jl | 2 +- src/api_methods/instruments.jl | 45 +++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index a8e5c58..a3a70ff 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -13,7 +13,7 @@ include("api_methods/events.jl") include("api_methods/field_names.jl") include("api_methods/files.jl") #include("api_methods/file_repository.jl") -#include("api_methods/instruments.jl") +include("api_methods/instruments.jl") include("api_methods/logging.jl") include("api_methods/metadata.jl") include("api_methods/projects.jl") diff --git a/src/api_methods/instruments.jl b/src/api_methods/instruments.jl index 10e0e02..18c2373 100644 --- a/src/api_methods/instruments.jl +++ b/src/api_methods/instruments.jl @@ -3,8 +3,17 @@ export export_instrument_event_mappings, export_PDF, import_instrument_event_mappings -function export_instrument_event_mappings(;format=:xml,arms=nothing,returnFormat=nothing) +function export_instrument_event_mappings(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + arms=nothing, + ) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:formEventMapping), format=REDCap_format(format), arms=arms, @@ -12,15 +21,34 @@ function export_instrument_event_mappings(;format=:xml,arms=nothing,returnFormat ) end -function export_instruments(;format=:xml) +function export_instruments(; + url=REDCap_url(url), + token=REDCap_token(token), + format=REDCap_format(format), + ) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:instrument), format=REDCap_format(format), ) end -function export_PDF(;record=nothing,event=nothing,instrument=nothing,repeat_instance=1,allRecords=nothing,compactDisplay="FALSE",returnFormat=:xml) +function export_PDF(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + returnFormat::redcap_returnFormat_parameter=nothing, + record=nothing, + event=nothing, + instrument=nothing, + repeat_instance=nothing, + allRecords=nothing, + compactDisplay=nothing, +) REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:pdf), record=record, event=event, @@ -32,10 +60,19 @@ function export_PDF(;record=nothing,event=nothing,instrument=nothing,repeat_inst ) end -function import_instrument_event_mappings(;format=:xml,data=nothing,returnFormat=nothing) +function import_instrument_event_mappings(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + data=nothing, + ) + #TODO: Here and throughout, enforce that this function cannot #behave like an export, since the API calls are similar REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:formEventMapping), format=REDCap_format(format), data=data, From 658f46de78ea71eb11a850b934b173dd447dc510 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 20:02:07 -0400 Subject: [PATCH 13/28] Update filerepository methods --- src/REDCap.jl | 2 +- src/api_methods/file_repository.jl | 64 +++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/REDCap.jl b/src/REDCap.jl index a3a70ff..3d7ae3d 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -12,7 +12,7 @@ include("api_methods/data_access_groups.jl") include("api_methods/events.jl") include("api_methods/field_names.jl") include("api_methods/files.jl") -#include("api_methods/file_repository.jl") +include("api_methods/file_repository.jl") include("api_methods/instruments.jl") include("api_methods/logging.jl") include("api_methods/metadata.jl") diff --git a/src/api_methods/file_repository.jl b/src/api_methods/file_repository.jl index 39948a7..56d778b 100644 --- a/src/api_methods/file_repository.jl +++ b/src/api_methods/file_repository.jl @@ -4,8 +4,20 @@ export create_folder, export_list_of_folders, import_file_from_file_repository -function create_folder(;name=nothing,format=:xml,folder_id=nothing,dag_id=nothing,role_id=nothing,returnFormat=:xml) +function create_folder(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + name=nothing, +folder_id=nothing, +dag_id=nothing, +role_id=nothing, +) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:fileRepository), action=REDCap_action(:createFolder), name=name, @@ -17,8 +29,18 @@ function create_folder(;name=nothing,format=:xml,folder_id=nothing,dag_id=nothin ) end -function delete_file_from_file_repository(;name=nothing,format=:xml,doc_id=nothing,returnFormat=:xml) +function delete_file_from_file_repository(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + name=nothing, +doc_id=nothing, +) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:fileRepository), action=REDCap_action(:delete), doc_id=doc_id, @@ -26,17 +48,38 @@ function delete_file_from_file_repository(;name=nothing,format=:xml,doc_id=nothi ) end -function export_file_from_file_repository(;name=nothing,format=:xml,doc_id=nothing,returnFormat=:xml) +function export_file_from_file_repository(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + name=nothing, +doc_id=nothing, +) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:fileRepository), action=REDCap_action(:export), doc_id=doc_id, + format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), ) end -function export_list_of_folders(;name=nothing,format=:xml,folder_id=nothing,returnFormat=:xml) +function export_list_of_folders(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + name=nothing, +folder_id=nothing, +) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:fileRepository), action=REDCap_action(:list), name=name, @@ -46,8 +89,19 @@ function export_list_of_folders(;name=nothing,format=:xml,folder_id=nothing,retu ) end -function import_file_from_file_repository(;name=nothing,format=:xml,file=nothing,folder_id=nothing,returnFormat=:xml) +function import_file_from_file_repository(; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + name=nothing, +file=nothing, +folder_id=nothing, +) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), content=REDCap_content(:fileRepository), action=REDCap_action(:import), file=file, From 8fb2cc0ed4ca120e7d58fd8fa93977b2ba2290a6 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:29:00 -0400 Subject: [PATCH 14/28] Add REDCap_data type (currently unused) --- src/types.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/types.jl b/src/types.jl index 627270e..08b0240 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,3 +1,11 @@ +struct REDCap_data + id::Symbol + REDCap_data(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid data parameter")) +end +Base.display(x::REDCap_data) = Base.display(x.id) +Base.string(x::REDCap_data) = Base.string(x.id) +Base.convert(String,x::REDCap_data) = string(x) + struct REDCap_action id::Symbol REDCap_action(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid action parameter")) From 9f9526d1ba3a96db767ef9b610f3f3ad5af36da8 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:29:09 -0400 Subject: [PATCH 15/28] Add test --- test/runtests.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index f40d9e3..41d5881 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,7 +11,7 @@ else @test export_version() == "14.5.8" #@test create_project(data="""[{"project_title":"My New REDCap Project","purpose":"0"}]""",format="json") |> REDCap.is_valid_token -#TODO: account for running test without token in ENV +#TODO: account for running test without token in E #TODO: more tests like this, checking the API's return value #= @@ -23,6 +23,8 @@ import_users(data="""username\naharris""", format=:csv) =# begin + + @test create_project(data=Dict(:project_title=>"AAA","purpose"=>1)) == "{\"error\":\"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other).\"}" token = create_project(data=Dict(:project_title=>"$(now())",:purpose=>0)) export_project_XML(token=token) export_project_info(token=token) From 4972aaeefcf691a4fdb61c019ceb0ba50e588a47 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:29:58 -0400 Subject: [PATCH 16/28] Accept Dict or filename for data parameter --- src/api_methods/projects.jl | 42 +++++++++++++++++++++++++++++-------- src/utils.jl | 5 +++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 3f2581d..41507f1 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -5,27 +5,51 @@ export create_project, function create_project(; data::redcap_data_parameter, + url::redcap_url_parameter=get_url(), + token::redcap_super_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + odm::redcap_odm_parameter=nothing, + ) + create_project(data;token=token,url=url,format=format,returnFormat=returnFormat,odm=odm) +end + +function create_project(data::Dict; url::redcap_url_parameter=get_url(), token::redcap_super_token_parameter=get_token(), format::redcap_format_parameter=nothing, returnFormat::redcap_returnFormat_parameter=nothing, odm::redcap_odm_parameter=nothing,) + @assert Symbol.(keys(data)) ⊆ [:project_title, :purpose, :purpose_other, :project_notes, :is_longitudinal, :surveys_enabled, :record_autonumbering_enabled,] + #TODO: check when data isn't a Dict? + if [:project_title, :purpose] ⊈ Symbol.(keys(data)); throw(ArgumentError("The data field must include a project title and purpose")) end + data= #TODO: best way to avoid type change? + # maybe function to map (Dict,String) to (String,String) - if isa(data,Dict) - @assert Symbol.(keys(data)) ⊆ [:project_title, :purpose, :purpose_other, :project_notes, :is_longitudinal, :surveys_enabled, :record_autonumbering_enabled,] - #TODO: check when data isn't a Dict? - if [:project_title, :purpose] ⊈ Symbol.(keys(data)); throw(ArgumentError("The data field must include a project title and purpose")) end - data="[$(JSON.json(data))]" #TODO: best way to avoid type change? - # maybe function to map (Dict,String) to (String,String) - format=:json - end + #TODO: better to use xml, since this is the default format for returns? + REDCap.request(; + content=REDCap_content(:project), + format=:json, + returnFormat=REDCap_format(returnFormat), + data="[$(JSON.json(data))]", + url=REDCap_url(url), + token=REDCap_super_token(token), + odm=odm, + ) +end +function create_project(data::String; + url::redcap_url_parameter=get_url(), + token::redcap_super_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + odm::redcap_odm_parameter=nothing,) REDCap.request(; content=REDCap_content(:project), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), - data=data, + data=read(data, String), url=REDCap_url(url), token=REDCap_super_token(token), odm=odm, diff --git a/src/utils.jl b/src/utils.jl index d467b11..863ce3a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,12 +2,17 @@ function request(; url::URI, token::Union{REDCap_token, REDCap_super_token}, content::REDCap_content, + data=nothing, kwargs...) #TODO: replace interpolation with string()? html_request_body = assemble_html_body(;kwargs...) html_request_body["token"] = token html_request_body["content"] = "$content" + #TODO: Can't the data parameter be nothing and still hav an effect in at least 1 function? + if !isnothing(data); html_request_body["data"] = "$data" end + + #println(html_request_body) response = HTTP.post( URI(url); From 0c02bb5f0f38484761c3e6e7eca97cefc4e2674a Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:17:53 -0400 Subject: [PATCH 17/28] Add type assertion --- src/utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.jl b/src/utils.jl index 863ce3a..fb368b7 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -45,6 +45,7 @@ function assemble_html_body(;kwargs...) body = Dict{String, Union{String, IOBuffer}}() if !isempty(kwargs) for (parameter,value) in kwargs + value::redcap_generic_parameter if !isnothing(value) #if parameter ∈ [:data, :filterLogic] #body["$parameter"] = IOBuffer(string(value)) From adbfd1b0429e1d4c3d7f128d9860c36d825be3c9 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 00:42:16 -0400 Subject: [PATCH 18/28] Test types for project data import --- src/api_methods/projects.jl | 41 ++++++++++++++++++++++++++++++------- src/utils.jl | 2 +- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 41507f1..77d9216 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -11,6 +11,7 @@ function create_project(; returnFormat::redcap_returnFormat_parameter=nothing, odm::redcap_odm_parameter=nothing, ) + #TODO: should format be inferred? create_project(data;token=token,url=url,format=format,returnFormat=returnFormat,odm=odm) end @@ -20,6 +21,12 @@ function create_project(data::Dict; format::redcap_format_parameter=nothing, returnFormat::redcap_returnFormat_parameter=nothing, odm::redcap_odm_parameter=nothing,) + + #TODO: what is backgroundProcess=true + + #TODO: maybe this isn't a priority - REDCap's error checking is fine here + # On the other hand, it's great to have this list visible... + # I guess put these in the documentation @assert Symbol.(keys(data)) ⊆ [:project_title, :purpose, :purpose_other, :project_notes, :is_longitudinal, :surveys_enabled, :record_autonumbering_enabled,] #TODO: check when data isn't a Dict? if [:project_title, :purpose] ⊈ Symbol.(keys(data)); throw(ArgumentError("The data field must include a project title and purpose")) end @@ -100,22 +107,42 @@ function export_project_XML(; ) end -function import_project_info(;name=nothing,format=nothing,data, +function import_project_info(; + format=nothing,data, + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + ) + + import_project_info(data; token=token, url=url, format=format) +end + +function import_project_info(data::Dict; + format=nothing, url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), ) + @assert Symbol.(keys(data)) ⊆ [:project_title, :project_language, :purpose, :purpose_other, :project_notes, :custom_record_label, :secondary_unique_field, :is_longitudinal, :surveys_enabled, :scheduling_enabled, :record_autonumbering_enabled, :randomization_enabled, :project_irb_number, :project_grant_number, :project_pi_firstname, :project_pi_lastname, :display_today_now_button, :bypass_branching_erase_field_prompt] + + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), + content=REDCap_content(:project_settings), + format=REDCap_format(:json), + data="[$(JSON.json(data))]" + ) +end - if isa(data,Dict) - @assert Symbol.(keys(data)) ⊆ [:project_title, :project_language, :purpose, :purpose_other, :project_notes, :custom_record_label, :secondary_unique_field, :is_longitudinal, :surveys_enabled, :scheduling_enabled, :record_autonumbering_enabled, :randomization_enabled, :project_irb_number, :project_grant_number, :project_pi_firstname, :project_pi_lastname, :display_today_now_button, :bypass_branching_erase_field_prompt] - data="[$(JSON.json(data))]" - format=:json - end +#TODO: only the CSV version works here? +function import_project_info(data::String; + format=nothing, + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), ) REDCap.request(; url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:project_settings), format=REDCap_format(format), - data=data, + data=read(data,String) ) end diff --git a/src/utils.jl b/src/utils.jl index fb368b7..9811c80 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -42,7 +42,7 @@ function request(; end function assemble_html_body(;kwargs...) - body = Dict{String, Union{String, IOBuffer}}() + body = Dict{String, String}() if !isempty(kwargs) for (parameter,value) in kwargs value::redcap_generic_parameter From b01ecef6ec9b0c434c2d8d86bf06a11c0112d184 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 09:33:09 -0400 Subject: [PATCH 19/28] Timestamps can be String or DateTime --- src/api_methods/logging.jl | 5 +++-- src/api_methods/projects.jl | 1 + src/api_methods/redcap.jl | 1 + src/types.jl | 16 +++++++++++++++- test/runtests.jl | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/api_methods/logging.jl b/src/api_methods/logging.jl index c32cbc2..093c82e 100644 --- a/src/api_methods/logging.jl +++ b/src/api_methods/logging.jl @@ -1,5 +1,6 @@ export export_logging +#TODO: why does the returnFormat parameter not work? function export_logging(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), @@ -22,7 +23,7 @@ function export_logging(; user=user, record=record, dag=dag, - beginTime=beginTime, - endTime=endTime, + beginTime=REDCap_datetime(beginTime), + endTime=REDCap_datetime(endTime), ) end diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 77d9216..c63a05b 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -77,6 +77,7 @@ function export_project_info(; ) end +#TODO: should this write to a file? function export_project_XML(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), diff --git a/src/api_methods/redcap.jl b/src/api_methods/redcap.jl index 05965de..e0bfb39 100644 --- a/src/api_methods/redcap.jl +++ b/src/api_methods/redcap.jl @@ -1,5 +1,6 @@ export export_version +#TODO: should this return a VersionInfo? function export_version(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), diff --git a/src/types.jl b/src/types.jl index 08b0240..214b63b 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,3 +1,6 @@ + + +#TODO: currently unused struct REDCap_data id::Symbol REDCap_data(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid data parameter")) @@ -40,7 +43,18 @@ const redcap_format_parameter = Union{String, Symbol, Nothing} const redcap_returnFormat_parameter = redcap_format_parameter #const redcap_formatter = Union{Symbol, Nothing} const redcap_symbol = Union{Symbol, Nothing} -const redcap_timestamp = Union{DateTime, Nothing} #TODO: YYYY-MM-DD HH:MM +const redcap_timestamp = Union{Date, DateTime, String,Nothing} #TODO: YYYY-MM-DD HH:MM + +#TODO: currently unused +REDCap_datetime(x::String) = DateTime(x,"yyyy-m-dd H:M") +REDCap_datetime(x::Date) = DateTime(x) +REDCap_datetime(x::DateTime) = x +REDCap_datetime(x::Nothing) = nothing + +#TODO: add regex check occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) + + + redcap_generic_parameter = Union{ #redcap_action_parameter, diff --git a/test/runtests.jl b/test/runtests.jl index 41d5881..30931cf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,6 +34,7 @@ begin @assert "1" == import_project_info(token=token,data=Dict(:project_title=>"$(now())",:purpose=>0)) export_logging(token=token, format=:json) |>JSON.parse |> DataFrame + @test export_logging(token=token,format=:json, endTime="1999-01-01") |> JSON.parse |> DataFrame == DataFrame() #TODO: for CSV inputs, use triple quotes, and add a comma at the end if the last inner character is also a quote # Can this always be done, or only when the last column is blank? From c3e22f19115c9b0ed27dd336fa32165daeb241d5 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 09:59:10 -0400 Subject: [PATCH 20/28] Add missing parameter --- src/api_methods/reports.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index 293ff14..f75a872 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -4,6 +4,7 @@ function export_reports(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), format::redcap_format_parameter=nothing, + returnFormat::redcap_format_parameter=nothing, fields::redcap_array=nothing, report_id=nothing, rawOrLabel=nothing, From cced65fae7a326ffe2c505d6524c11a5239c4646 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 13:12:02 -0400 Subject: [PATCH 21/28] Support filename or Dict for data (for now, requires format=:json) --- src/api_methods/arms.jl | 2 +- src/api_methods/data_access_groups.jl | 4 +-- src/api_methods/events.jl | 2 +- src/api_methods/instruments.jl | 2 +- src/api_methods/logging.jl | 1 + src/api_methods/metadata.jl | 40 +++++++++++++++++++++++++-- src/api_methods/projects.jl | 31 +++++++++++++++++---- src/api_methods/records.jl | 8 +++--- src/api_methods/user_roles.jl | 4 +-- src/api_methods/users.jl | 4 ++- src/types.jl | 11 ++------ test/runtests.jl | 21 +++++++------- 12 files changed, 93 insertions(+), 37 deletions(-) diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index 20afde5..93fdea1 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -51,7 +51,7 @@ function import_arms(; override=override, action=REDCap_action(:import), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index ae6ee02..bee11e7 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -63,7 +63,7 @@ function import_DAGs(; content=REDCap_content(:dag), action=REDCap_action(:import), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end @@ -81,7 +81,7 @@ function import_user_DAG_assignment(; token=REDCap_token(token), content=REDCap_content(:userDagMapping), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index 28dc5b1..e73446e 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -52,7 +52,7 @@ function import_events(; content=REDCap_content(:event), action=REDCap_action(:import), override=override, - data=data, + data=REDCap_data(data), ) end diff --git a/src/api_methods/instruments.jl b/src/api_methods/instruments.jl index 18c2373..16b93a5 100644 --- a/src/api_methods/instruments.jl +++ b/src/api_methods/instruments.jl @@ -75,7 +75,7 @@ function import_instrument_event_mappings(; token=REDCap_token(token), content=REDCap_content(:formEventMapping), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/logging.jl b/src/api_methods/logging.jl index 093c82e..d6c80a5 100644 --- a/src/api_methods/logging.jl +++ b/src/api_methods/logging.jl @@ -1,6 +1,7 @@ export export_logging #TODO: why does the returnFormat parameter not work? +#TODO: What permissible values for logtype? function export_logging(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), diff --git a/src/api_methods/metadata.jl b/src/api_methods/metadata.jl index 1e1865a..5966e8b 100644 --- a/src/api_methods/metadata.jl +++ b/src/api_methods/metadata.jl @@ -1,5 +1,6 @@ export export_metadata, import_metadata +#TODO: For most export functions, returnFormat seems to have no effect function export_metadata(; url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), @@ -21,20 +22,55 @@ function export_metadata(; end function import_metadata(; + data::redcap_data_parameter, url::redcap_url_parameter=get_url(), token::redcap_token_parameter=get_token(), format::redcap_format_parameter=nothing, - data::redcap_data_parameter=nothing, returnFormat::redcap_returnFormat_parameter=nothing, ) + #import_metadata(data; url=url, token=token, returnFormat=returnFormat) REDCap.request(; url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:metadata), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end +#= +function import_metadata(data::Dict; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + ) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), + content=REDCap_content(:metadata), + format=REDCap_format(:json), + data="[$(JSON.json(data))]", + returnFormat=REDCap_format(returnFormat), + ) +end + +function import_metadata(data::String; + url::redcap_url_parameter=get_url(), + token::redcap_token_parameter=get_token(), + format::redcap_format_parameter=nothing, + returnFormat::redcap_returnFormat_parameter=nothing, + ) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), + content=REDCap_content(:metadata), + format=REDCap_format(format), + data=read(data, String), + returnFormat=REDCap_format(returnFormat), + ) +end + +=# diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index c63a05b..4ba8d6d 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -1,7 +1,8 @@ -export create_project, +export + create_project, export_project_info, export_project_XML, - import_project_info + import_project_info #TODO: not working, and there's no official API example... are we supposed to just pass this data in create_project? function create_project(; data::redcap_data_parameter, @@ -11,9 +12,19 @@ function create_project(; returnFormat::redcap_returnFormat_parameter=nothing, odm::redcap_odm_parameter=nothing, ) + REDCap.request(; + content=REDCap_content(:project), + format=REDCap_format(format), + returnFormat=REDCap_format(returnFormat), + data=REDCap_data(data), + url=REDCap_url(url), + token=REDCap_super_token(token), + odm=odm, + ) #TODO: should format be inferred? - create_project(data;token=token,url=url,format=format,returnFormat=returnFormat,odm=odm) + #create_project(data;token=token,url=url,format=format,returnFormat=returnFormat,odm=odm) end +#= function create_project(data::Dict; url::redcap_url_parameter=get_url(), @@ -36,7 +47,7 @@ function create_project(data::Dict; #TODO: better to use xml, since this is the default format for returns? REDCap.request(; content=REDCap_content(:project), - format=:json, + format=REDCap_format(:json), returnFormat=REDCap_format(returnFormat), data="[$(JSON.json(data))]", url=REDCap_url(url), @@ -62,6 +73,7 @@ function create_project(data::String; odm=odm, ) end +=# function export_project_info(; url::redcap_url_parameter=get_url(), @@ -114,9 +126,17 @@ function import_project_info(; token::redcap_token_parameter=get_token(), ) - import_project_info(data; token=token, url=url, format=format) + #import_project_info(data; token=token, url=url, format=format) + REDCap.request(; + url=REDCap_url(url), + token=REDCap_token(token), + content=REDCap_content(:project_settings), + format=REDCap_format(format), + data=REDCap_data(data), + ) end +#= function import_project_info(data::Dict; format=nothing, url::redcap_url_parameter=get_url(), @@ -147,3 +167,4 @@ function import_project_info(data::String; ) end +=# diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index d9e94da..e6bf0f6 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -52,7 +52,7 @@ function export_records(; exportBlankForGrayFormStatus::redcap_bool=nothing ) REDCap.request( - data=data, + data=REDCap_data(data), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), @@ -83,7 +83,7 @@ function generate_next_record_name( ) REDCap.request( - data=data, + data=REDCap_data(data), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:generateNextRecordName), @@ -106,7 +106,7 @@ function import_records(; ) REDCap.request( - data=data, + data=REDCap_data(data), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), @@ -130,7 +130,7 @@ function rename_record(; ) REDCap.request( - data=data, + data=REDCap_data(data), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index 8b0ff0c..580e660 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -49,7 +49,7 @@ function import_user_roles(; token=REDCap_token(token), content=REDCap_content(:userRole), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end @@ -84,7 +84,7 @@ function import_user_role_assignments(; token=REDCap_token(token), content=REDCap_content(:userRoleMapping), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index d53f1d0..42f6838 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -40,18 +40,20 @@ function import_users(; data::redcap_data_parameter, ) + #= if isa(data,Dict) @assert Symbol.(keys(data)) ⊆ [:username, :expiration, :data_access_group, :design, :alerts, :user_rights, :data_access_groups, :data_export, :reports, :stats_and_charts, :manage_survey_participants, :calendar, :data_import_tool, :data_comparison_tool, :logging, :file_repository, :data_quality_create, :data_quality_execute, :api_export, :api_import, :mobile_app, :mobile_app_download_data, :record_create, :record_rename, :record_delete, :lock_records_customization, :lock_records, :lock_records_all_forms, :forms, :forms_export] data="[$(JSON.json(data))]" format=:json end + =# REDCap.request( url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:user), format=REDCap_format(format), - data=data, + data=REDCap_data(data), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/types.jl b/src/types.jl index 214b63b..6786098 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,13 +1,8 @@ -#TODO: currently unused -struct REDCap_data - id::Symbol - REDCap_data(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid data parameter")) -end -Base.display(x::REDCap_data) = Base.display(x.id) -Base.string(x::REDCap_data) = Base.string(x.id) -Base.convert(String,x::REDCap_data) = string(x) +#TODO: consier passing data and format and converting data based on format +REDCap_data(x::Dict)="[$(JSON.json(x))]" +REDCap_data(x::String)=read(x, String) struct REDCap_action id::Symbol diff --git a/test/runtests.jl b/test/runtests.jl index 30931cf..89bdbda 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -24,26 +24,27 @@ import_users(data="""username\naharris""", format=:csv) begin - @test create_project(data=Dict(:project_title=>"AAA","purpose"=>1)) == "{\"error\":\"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other).\"}" - token = create_project(data=Dict(:project_title=>"$(now())",:purpose=>0)) - export_project_XML(token=token) - export_project_info(token=token) + #TODO: for now, put a :json format tag when using a Dict + @test create_project(format=:json,data=Dict(:project_title=>"AAA","purpose"=>1)) == "{\"error\":\"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other).\"}" + project_token = create_project(format=:json,data=Dict(:project_title=>"$(now())",:purpose=>0)) + export_project_XML(token=project_token) + export_project_info(token=project_token) - export_metadata(token=token) + export_metadata(token=project_token) - @assert "1" == import_project_info(token=token,data=Dict(:project_title=>"$(now())",:purpose=>0)) - export_logging(token=token, format=:json) |>JSON.parse |> DataFrame - @test export_logging(token=token,format=:json, endTime="1999-01-01") |> JSON.parse |> DataFrame == DataFrame() + @assert "1" == import_project_info(format=:json,token=project_token,data=Dict(:project_title=>"$(now())",:purpose=>0)) + export_logging(token=project_token, format=:json) |>JSON.parse |> DataFrame + @test export_logging(token=project_token,format=:json, endTime="1999-01-01") |> JSON.parse |> DataFrame == DataFrame() #TODO: for CSV inputs, use triple quotes, and add a comma at the end if the last inner character is also a quote # Can this always be done, or only when the last column is blank? - import_DAGs(token=t,format=:csv,data="""data_access_group_name,unique_group_name + import_DAGs(token=project_token,format=:csv,data="""data_access_group_name,unique_group_name "CA Site", "FL Site", "New Site",""") - import_users(token=token,format=:xml,data=""" + import_users(token=project_token,format=:xml,data=""" harrispa From f1d170fe4171a167b4611145f15380a1cb183dfd Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:01:36 -0400 Subject: [PATCH 22/28] Update types --- src/api_methods/arms.jl | 22 ++--- src/api_methods/data_access_groups.jl | 40 ++++----- src/api_methods/events.jl | 20 ++--- src/api_methods/field_names.jl | 8 +- src/api_methods/file_repository.jl | 40 ++++----- src/api_methods/files.jl | 18 ++-- src/api_methods/instruments.jl | 22 ++--- src/api_methods/logging.jl | 12 +-- src/api_methods/metadata.jl | 38 ++++---- src/api_methods/projects.jl | 74 ++++++++-------- src/api_methods/records.jl | 88 +++++++++---------- src/api_methods/redcap.jl | 4 +- .../repeating_instruments_and_events.jl | 16 ++-- src/api_methods/reports.jl | 10 +-- src/api_methods/surveys.jl | 20 ++--- src/api_methods/user_roles.jl | 42 ++++----- src/api_methods/users.jl | 24 ++--- src/types.jl | 69 ++++++--------- test/runtests.jl | 2 + 19 files changed, 279 insertions(+), 290 deletions(-) diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index 93fdea1..fc00346 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -3,8 +3,8 @@ export delete_arms, import_arms function delete_arms(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), arms=nothing, ) @@ -18,10 +18,10 @@ function delete_arms(; end function export_arms(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, arms=nothing, ) @@ -36,11 +36,11 @@ function export_arms(; end function import_arms(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - data::redcap_data_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + data::redcap_data_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, override=0, ) diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index bee11e7..d2fc219 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -6,8 +6,8 @@ export delete_DAGs, switch_DAG function delete_DAGs(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), dags=nothing) REDCap.request(; @@ -20,9 +20,9 @@ function delete_DAGs(; end function export_DAGs(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, #TODO: This is one of those ones that only take a format parameter ) @@ -36,9 +36,9 @@ function export_DAGs(; end function export_user_DAG_assignment(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, ) REDCap.request(; @@ -50,11 +50,11 @@ function export_user_DAG_assignment(; end function import_DAGs(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - data::redcap_data_parameter=nothing, #TODO: It would be great to support a Dict here - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + data::redcap_data_input=nothing, #TODO: It would be great to support a Dict here + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request(; @@ -69,11 +69,11 @@ function import_DAGs(; end function import_user_DAG_assignment(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - data::redcap_data_parameter=nothing, - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + data::redcap_data_input=nothing, + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request(; @@ -87,8 +87,8 @@ function import_user_DAG_assignment(; end function switch_DAG(; - data::redcap_data_parameter=nothing, - url::redcap_url_parameter=get_url(), + data::redcap_data_input=nothing, + url::redcap_url_input=get_url(), dag=nothing) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index e73446e..77720be 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -3,8 +3,8 @@ export delete_events, export_events function delete_events(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), events=nothing, ) @@ -18,10 +18,10 @@ function delete_events(; end function export_events(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, arms=nothing, ) @@ -36,10 +36,10 @@ function export_events(; end function import_events(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, data=nothing, override=0, ) diff --git a/src/api_methods/field_names.jl b/src/api_methods/field_names.jl index af9bd4c..3991212 100644 --- a/src/api_methods/field_names.jl +++ b/src/api_methods/field_names.jl @@ -1,10 +1,10 @@ export export_list_of_export_field_names function export_list_of_export_field_names(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, field=nothing ) diff --git a/src/api_methods/file_repository.jl b/src/api_methods/file_repository.jl index 56d778b..107e3f5 100644 --- a/src/api_methods/file_repository.jl +++ b/src/api_methods/file_repository.jl @@ -5,10 +5,10 @@ export create_folder, import_file_from_file_repository function create_folder(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, name=nothing, folder_id=nothing, dag_id=nothing, @@ -30,10 +30,10 @@ role_id=nothing, end function delete_file_from_file_repository(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, name=nothing, doc_id=nothing, ) @@ -49,10 +49,10 @@ doc_id=nothing, end function export_file_from_file_repository(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, name=nothing, doc_id=nothing, ) @@ -69,10 +69,10 @@ doc_id=nothing, end function export_list_of_folders(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, name=nothing, folder_id=nothing, ) @@ -90,10 +90,10 @@ folder_id=nothing, end function import_file_from_file_repository(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, name=nothing, file=nothing, folder_id=nothing, diff --git a/src/api_methods/files.jl b/src/api_methods/files.jl index 47d4191..ab0435c 100644 --- a/src/api_methods/files.jl +++ b/src/api_methods/files.jl @@ -1,9 +1,9 @@ export delete_file, export_file, import_file function delete_file(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, field=nothing, event=nothing, @@ -24,9 +24,9 @@ function delete_file(; end function export_file(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, field=nothing, event=nothing, @@ -47,9 +47,9 @@ function export_file(; end function import_file(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, field=nothing, event=nothing, diff --git a/src/api_methods/instruments.jl b/src/api_methods/instruments.jl index 16b93a5..ee2e373 100644 --- a/src/api_methods/instruments.jl +++ b/src/api_methods/instruments.jl @@ -4,10 +4,10 @@ export export_instrument_event_mappings, import_instrument_event_mappings function export_instrument_event_mappings(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, arms=nothing, ) @@ -36,9 +36,9 @@ function export_instruments(; end function export_PDF(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, event=nothing, instrument=nothing, @@ -61,10 +61,10 @@ function export_PDF(; end function import_instrument_event_mappings(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, data=nothing, ) diff --git a/src/api_methods/logging.jl b/src/api_methods/logging.jl index d6c80a5..932341f 100644 --- a/src/api_methods/logging.jl +++ b/src/api_methods/logging.jl @@ -3,16 +3,16 @@ export export_logging #TODO: why does the returnFormat parameter not work? #TODO: What permissible values for logtype? function export_logging(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, logtype=nothing, user=nothing, record=nothing, dag=nothing, - beginTime::redcap_timestamp=nothing, - endTime::redcap_timestamp=nothing, + beginTime::redcap_timestamp_input=nothing, + endTime::redcap_timestamp_input=nothing, ) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/metadata.jl b/src/api_methods/metadata.jl index 5966e8b..5ee73cb 100644 --- a/src/api_methods/metadata.jl +++ b/src/api_methods/metadata.jl @@ -2,12 +2,12 @@ export export_metadata, import_metadata #TODO: For most export functions, returnFormat seems to have no effect function export_metadata(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - fields::redcap_array=nothing, - forms::redcap_array=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + fields::redcap_array_input=nothing, + forms::redcap_array_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request( @@ -22,11 +22,11 @@ function export_metadata(; end function import_metadata(; - data::redcap_data_parameter, - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + data::redcap_data_input, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) #import_metadata(data; url=url, token=token, returnFormat=returnFormat) @@ -42,10 +42,10 @@ end #= function import_metadata(data::Dict; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request(; url=REDCap_url(url), @@ -58,10 +58,10 @@ function import_metadata(data::Dict; end function import_metadata(data::String; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 4ba8d6d..a1fa620 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -5,12 +5,12 @@ export import_project_info #TODO: not working, and there's no official API example... are we supposed to just pass this data in create_project? function create_project(; - data::redcap_data_parameter, - url::redcap_url_parameter=get_url(), - token::redcap_super_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - odm::redcap_odm_parameter=nothing, + data::redcap_data_input, + url::redcap_url_input=get_url(), + token::redcap_super_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + odm::redcap_odm_input=nothing, ) REDCap.request(; content=REDCap_content(:project), @@ -27,11 +27,11 @@ end #= function create_project(data::Dict; - url::redcap_url_parameter=get_url(), - token::redcap_super_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - odm::redcap_odm_parameter=nothing,) + url::redcap_url_input=get_url(), + token::redcap_super_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + odm::redcap_odm_input=nothing,) #TODO: what is backgroundProcess=true @@ -57,11 +57,11 @@ function create_project(data::Dict; end function create_project(data::String; - url::redcap_url_parameter=get_url(), - token::redcap_super_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - odm::redcap_odm_parameter=nothing,) + url::redcap_url_input=get_url(), + token::redcap_super_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + odm::redcap_odm_input=nothing,) REDCap.request(; content=REDCap_content(:project), @@ -76,9 +76,9 @@ end =# function export_project_info(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request(; @@ -91,18 +91,18 @@ end #TODO: should this write to a file? function export_project_XML(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, - - returnMetadataOnly::redcap_bool=nothing, - records::redcap_array=nothing, - fields::redcap_array=nothing, - events::redcap_array=nothing, - exportSurveyFields::redcap_bool=nothing, - exportDataAccessGroups::redcap_bool=nothing, - filterLogic::redcap_filterLogic_parameter=nothing, - exportFiles::redcap_bool=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, + + returnMetadataOnly::redcap_bool_input=nothing, + records::redcap_array_input=nothing, + fields::redcap_array_input=nothing, + events::redcap_array_input=nothing, + exportSurveyFields::redcap_bool_input=nothing, + exportDataAccessGroups::redcap_bool_input=nothing, + filterLogic::redcap_filterLogic_input=nothing, + exportFiles::redcap_bool_input=nothing, ) REDCap.request(; url=REDCap_url(url), @@ -122,8 +122,8 @@ end function import_project_info(; format=nothing,data, - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), ) #import_project_info(data; token=token, url=url, format=format) @@ -139,8 +139,8 @@ end #= function import_project_info(data::Dict; format=nothing, - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), ) + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), ) @assert Symbol.(keys(data)) ⊆ [:project_title, :project_language, :purpose, :purpose_other, :project_notes, :custom_record_label, :secondary_unique_field, :is_longitudinal, :surveys_enabled, :scheduling_enabled, :record_autonumbering_enabled, :randomization_enabled, :project_irb_number, :project_grant_number, :project_pi_firstname, :project_pi_lastname, :display_today_now_button, :bypass_branching_erase_field_prompt] REDCap.request(; @@ -155,8 +155,8 @@ end #TODO: only the CSV version works here? function import_project_info(data::String; format=nothing, - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), ) + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), ) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index e6bf0f6..b0b9442 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -6,13 +6,13 @@ export delete_records, function delete_records(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - records::redcap_array, #TODO: required? - arm::redcap_generic_parameter=nothing, - instrument::redcap_generic_parameter=nothing, - event::redcap_generic_parameter=nothing, - repeat_instance::redcap_generic_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + records::redcap_array_input, #TODO: required? + arm::redcap_generic_input=nothing, + instrument::redcap_generic_input=nothing, + event::redcap_generic_input=nothing, + repeat_instance::redcap_generic_input=nothing, ) REDCap.request( @@ -29,27 +29,27 @@ function delete_records(; end function export_records(; - data::redcap_data_parameter, - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - type::redcap_generic_parameter=nothing, - records::redcap_array=nothing, - fields::redcap_array=nothing, - forms::redcap_array=nothing, - events::redcap_array=nothing, - rawOrLabel::redcap_generic_parameter=nothing, - rawOrLabelHeaders::redcap_generic_parameter=nothing, - exportCheckboxLabel::redcap_bool=false, - returnFormat::redcap_generic_parameter=nothing, - exportSurveyFields::redcap_bool=false, - exportDataAccessGroups::redcap_bool=false, - filterLogic::redcap_filterLogic_parameter=nothing, - dateRangeBegin::redcap_timestamp=nothing, - dateRangeEnd::redcap_timestamp=nothing, - csvDelimiter::redcap_generic_parameter=nothing, - decimalCharacter::redcap_generic_parameter=nothing, - exportBlankForGrayFormStatus::redcap_bool=nothing + data::redcap_data_input, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + type::redcap_generic_input=nothing, + records::redcap_array_input=nothing, + fields::redcap_array_input=nothing, + forms::redcap_array_input=nothing, + events::redcap_array_input=nothing, + rawOrLabel::redcap_generic_input=nothing, + rawOrLabelHeaders::redcap_generic_input=nothing, + exportCheckboxLabel::redcap_bool_input=false, + returnFormat::redcap_generic_input=nothing, + exportSurveyFields::redcap_bool_input=false, + exportDataAccessGroups::redcap_bool_input=false, + filterLogic::redcap_filterLogic_input=nothing, + dateRangeBegin::redcap_timestamp_input=nothing, + dateRangeEnd::redcap_timestamp_input=nothing, + csvDelimiter::redcap_generic_input=nothing, + decimalCharacter::redcap_generic_input=nothing, + exportBlankForGrayFormStatus::redcap_bool_input=nothing ) REDCap.request( data=REDCap_data(data), @@ -78,8 +78,8 @@ end #if data == nothing, this is an export request function generate_next_record_name( - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), ) REDCap.request( @@ -92,16 +92,16 @@ end #if data == nothing, this is an export request function import_records(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - type::redcap_generic_parameter=nothing, - overwriteBehavior::redcap_bool=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + type::redcap_generic_input=nothing, + overwriteBehavior::redcap_bool_input=nothing, forceAutoNumber=nothing, - data::redcap_data_parameter=nothing, - dateFormat::redcap_generic_parameter=nothing, - csvDelimiter::redcap_generic_parameter=nothing, + data::redcap_data_input=nothing, + dateFormat::redcap_generic_input=nothing, + csvDelimiter::redcap_generic_input=nothing, returnContent=nothing, ) @@ -122,11 +122,11 @@ function import_records(; end function rename_record(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - record::redcap_generic_parameter, - new_record_name::redcap_generic_parameter, - arm::redcap_generic_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + record::redcap_generic_input, + new_record_name::redcap_generic_input, + arm::redcap_generic_input=nothing, ) REDCap.request( diff --git a/src/api_methods/redcap.jl b/src/api_methods/redcap.jl index e0bfb39..f4c6c00 100644 --- a/src/api_methods/redcap.jl +++ b/src/api_methods/redcap.jl @@ -2,8 +2,8 @@ export export_version #TODO: should this return a VersionInfo? function export_version(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), ) REDCap.request(; diff --git a/src/api_methods/repeating_instruments_and_events.jl b/src/api_methods/repeating_instruments_and_events.jl index 184ee17..4c551c2 100644 --- a/src/api_methods/repeating_instruments_and_events.jl +++ b/src/api_methods/repeating_instruments_and_events.jl @@ -2,9 +2,9 @@ export export_repeating_instruments_and_events, import_repeating_instruments_and_events function export_repeating_instruments_and_events(; - url::redcap_url_parameter=get_url(), - token::redcap_super_token_parameter=get_token(), - format::redcap_format_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_super_token_input=get_token(), + format::redcap_format_input=nothing, ) REDCap.request( @@ -16,11 +16,11 @@ function export_repeating_instruments_and_events(; end function import_repeating_instruments_and_events(; - url::redcap_url_parameter=get_url(), - token::redcap_super_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - data::redcap_data_parameter, #TODO: the docs mention a super API token may be used here...? + url::redcap_url_input=get_url(), + token::redcap_super_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + data::redcap_data_input, #TODO: the docs mention a super API token may be used here...? #TODO: data parameter is essential to distringuish from an export #TODO: does is make sense to define one method in terms of the other? ) diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index f75a872..d9bd6e0 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -1,11 +1,11 @@ export export_reports function export_reports(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_format_parameter=nothing, - fields::redcap_array=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_format_input=nothing, + fields::redcap_array_input=nothing, report_id=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, diff --git a/src/api_methods/surveys.jl b/src/api_methods/surveys.jl index 36c7e13..32187b3 100644 --- a/src/api_methods/surveys.jl +++ b/src/api_methods/surveys.jl @@ -4,9 +4,9 @@ export_survey_queue_link, export_survey_return_code function export_survey_link(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, instrument=nothing, event=nothing, @@ -26,10 +26,10 @@ function export_survey_link(; end function export_survey_participants(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, instrument=nothing, event=nothing, repeat_instance=nothing, @@ -58,9 +58,9 @@ function export_survey_queue_link(;record=nothing,returnFormat=:xml) end function export_survey_return_code(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + returnFormat::redcap_returnFormat_input=nothing, record=nothing, instrument=nothing, event=nothing, diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index 580e660..e17e660 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -5,9 +5,9 @@ export export_user_roles, import_user_role_assignments function delete_user_roles(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - users::redcap_array=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + users::redcap_array_input=nothing, ) REDCap.request( @@ -21,10 +21,10 @@ end function export_user_roles(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request( @@ -37,11 +37,11 @@ function export_user_roles(; end function import_user_roles(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - data::redcap_data_parameter, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + data::redcap_data_input, ) REDCap.request( @@ -56,10 +56,10 @@ end function export_user_role_assignments(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request( @@ -72,11 +72,11 @@ function export_user_role_assignments(; end function import_user_role_assignments(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - data::redcap_data_parameter, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + data::redcap_data_input, ) REDCap.request( diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index 42f6838..121ee5a 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -3,9 +3,9 @@ export export_users, delete_users function delete_users(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - users::redcap_array=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + users::redcap_array_input=nothing, ) REDCap.request( url=REDCap_url(url), @@ -17,10 +17,10 @@ function delete_users(; end function export_users(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, ) REDCap.request( @@ -33,11 +33,11 @@ function export_users(; end function import_users(; - url::redcap_url_parameter=get_url(), - token::redcap_token_parameter=get_token(), - format::redcap_format_parameter=nothing, - returnFormat::redcap_returnFormat_parameter=nothing, - data::redcap_data_parameter, + url::redcap_url_input=get_url(), + token::redcap_token_input=get_token(), + format::redcap_format_input=nothing, + returnFormat::redcap_returnFormat_input=nothing, + data::redcap_data_input, ) #= diff --git a/src/types.jl b/src/types.jl index 6786098..75951ea 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,6 +1,6 @@ - #TODO: consier passing data and format and converting data based on format +const redcap_data_input = Union{String, Dict} REDCap_data(x::Dict)="[$(JSON.json(x))]" REDCap_data(x::String)=read(x, String) @@ -20,52 +20,39 @@ Base.display(x::REDCap_content) = Base.display(x.id) Base.string(x::REDCap_content) = Base.string(x.id) Base.convert(String,x::REDCap_content) = string(x) -const redcap_url_parameter = String +const redcap_url_input = String #TODO: help users fix formatting errors - I left out the final slash and had trouble debugging -REDCap_url(x::redcap_url_parameter) = occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) +# Maybe a function that checks for common mistakes +REDCap_url(x::redcap_url_input) = occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) -const redcap_token_parameter = String -const redcap_super_token_parameter = String -#const redcap_action_parameter = Union{Symbol, Nothing} -const redcap_data_parameter = Any -#const redcap_data_parameter = Union{IOStream, Dict, String, Nothing} #TODO: this can be nothing in REDCap.request(), but must be mandatory wherever it is a method parameter. Otherwise, it changes the method behavior, which would contradict the guarantee of the function name -const redcap_filterLogic_parameter = Union{String, Nothing} -const redcap_odm_parameter = Union{String, Nothing} +const redcap_token_input = String +const redcap_super_token_input = String +const redcap_filterLogic_input = Union{String, Nothing} +const redcap_odm_input = Union{String, Nothing} -const redcap_array = Union{Array, Nothing} -const redcap_bool = Union{Bool, Nothing} -const redcap_format_parameter = Union{String, Symbol, Nothing} -const redcap_returnFormat_parameter = redcap_format_parameter -#const redcap_formatter = Union{Symbol, Nothing} -const redcap_symbol = Union{Symbol, Nothing} -const redcap_timestamp = Union{Date, DateTime, String,Nothing} #TODO: YYYY-MM-DD HH:MM +const redcap_array_input = Union{Array, Nothing} +const redcap_bool_input = Union{Bool, Nothing} +const redcap_format_input = Union{String, Symbol, Nothing} +const redcap_returnFormat_input = redcap_format_input -#TODO: currently unused +const redcap_timestamp_input = Union{Date, DateTime, String,Nothing} REDCap_datetime(x::String) = DateTime(x,"yyyy-m-dd H:M") REDCap_datetime(x::Date) = DateTime(x) REDCap_datetime(x::DateTime) = x REDCap_datetime(x::Nothing) = nothing -#TODO: add regex check occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) - - - - -redcap_generic_parameter = Union{ - #redcap_action_parameter, - redcap_data_parameter, - redcap_filterLogic_parameter, - redcap_odm_parameter, - redcap_array, - redcap_bool, - redcap_format_parameter, - #redcap_formatter, - redcap_symbol, - redcap_timestamp, +redcap_generic_input = Union{ + redcap_data_input, + redcap_filterLogic_input, + redcap_odm_input, + redcap_array_input, + redcap_bool_input, + redcap_format_input, + redcap_timestamp_input, } struct REDCap_format - id::redcap_format_parameter + id::redcap_format_input REDCap_format(id::Symbol) = id ∈ [:csv,:json,:xml] ? new(id) : throw(ArgumentError("Invalid format parameter")) REDCap_format(id::String) = id ∈ ["csv","json","xml"] ? new(Symbol(id)) : throw(ArgumentError("Invalid format parameter")) REDCap_format(id::Nothing) = nothing @@ -90,12 +77,12 @@ Base.display(x::REDCap_super_token) = display(x.id) Base.string(x::REDCap_super_token) = string(x.id) Base.convert(String,x::REDCap_super_token) = string(x) -#const redcap_token_parameter = Union{REDCap_token, REDCap_super_token} - -#const redcap_either_token = Union{redcap_token_parameter, redcap_super_token_parameter} - #macro redcap_token_str(t); REDCap_token(t) ; end #TODO: Is this macro helpful in any way? -#TODO: add type assertions for all the kwargs somewhere? -# Or assert they're in any type +redcap_generic_parameter = Union{ + REDCap_format, + DateTime, + String, + Nothing, + } diff --git a/test/runtests.jl b/test/runtests.jl index 89bdbda..9224aa4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -39,6 +39,7 @@ begin #TODO: for CSV inputs, use triple quotes, and add a comma at the end if the last inner character is also a quote # Can this always be done, or only when the last column is blank? +#= import_DAGs(token=project_token,format=:csv,data="""data_access_group_name,unique_group_name "CA Site", "FL Site", @@ -63,6 +64,7 @@ begin """) +=# #CSV.read(export_users(format=:csv) |> IOBuffer, DataFrame ) From c499334e19e4b9c36fc0459a3ff5100747b3bcc0 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:40:14 -0400 Subject: [PATCH 23/28] Clean up --- src/api_methods/data_access_groups.jl | 2 +- src/types.jl | 2 -- src/utils.jl | 5 +++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index d2fc219..df04b50 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -52,7 +52,7 @@ end function import_DAGs(; url::redcap_url_input=get_url(), token::redcap_token_input=get_token(), - data::redcap_data_input=nothing, #TODO: It would be great to support a Dict here + data::redcap_data_input=nothing, format::redcap_format_input=nothing, returnFormat::redcap_returnFormat_input=nothing, ) diff --git a/src/types.jl b/src/types.jl index 75951ea..4609a3a 100644 --- a/src/types.jl +++ b/src/types.jl @@ -77,8 +77,6 @@ Base.display(x::REDCap_super_token) = display(x.id) Base.string(x::REDCap_super_token) = string(x.id) Base.convert(String,x::REDCap_super_token) = string(x) -#macro redcap_token_str(t); REDCap_token(t) ; end #TODO: Is this macro helpful in any way? - redcap_generic_parameter = Union{ REDCap_format, DateTime, diff --git a/src/utils.jl b/src/utils.jl index 9811c80..836e91d 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,3 +1,5 @@ +#TODO: add something to automatically break files into < 500kb chunks? + function request(; url::URI, token::Union{REDCap_token, REDCap_super_token}, @@ -51,8 +53,7 @@ function assemble_html_body(;kwargs...) #body["$parameter"] = IOBuffer(string(value)) if isa(value, Array) for (i, item) in enumerate(value) - #TODO: define print functions for custom internal types - body["$parameter[$(i-1)]"] = "$item" + body["$parameter[$(i-1)]"] = string(item) end else body["$parameter"] = "$value" From 7f538b8abc04d938ebf96a09e2b33bec0942aa22 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:48:19 -0400 Subject: [PATCH 24/28] Add individual test files --- test/api_methods/arms.jl | 1 + test/api_methods/data_access_groups.jl | 1 + test/api_methods/events.jl | 1 + test/api_methods/field_names.jl | 1 + test/api_methods/file_repository.jl | 1 + test/api_methods/files.jl | 1 + test/api_methods/instruments.jl | 1 + test/api_methods/logging.jl | 1 + test/api_methods/metadata.jl | 1 + test/api_methods/projects.jl | 1 + test/api_methods/records.jl | 1 + test/api_methods/redcap.jl | 1 + .../repeating_instruments_and_events.jl | 1 + test/api_methods/reports.jl | 1 + test/api_methods/surveys.jl | 1 + test/api_methods/user_roles.jl | 1 + test/api_methods/users.jl | 1 + test/runtests.jl | 20 +++++++++++++++++++ 18 files changed, 37 insertions(+) create mode 100644 test/api_methods/arms.jl create mode 100644 test/api_methods/data_access_groups.jl create mode 100644 test/api_methods/events.jl create mode 100644 test/api_methods/field_names.jl create mode 100644 test/api_methods/file_repository.jl create mode 100644 test/api_methods/files.jl create mode 100644 test/api_methods/instruments.jl create mode 100644 test/api_methods/logging.jl create mode 100644 test/api_methods/metadata.jl create mode 100644 test/api_methods/projects.jl create mode 100644 test/api_methods/records.jl create mode 100644 test/api_methods/redcap.jl create mode 100644 test/api_methods/repeating_instruments_and_events.jl create mode 100644 test/api_methods/reports.jl create mode 100644 test/api_methods/surveys.jl create mode 100644 test/api_methods/user_roles.jl create mode 100644 test/api_methods/users.jl diff --git a/test/api_methods/arms.jl b/test/api_methods/arms.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/arms.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/data_access_groups.jl b/test/api_methods/data_access_groups.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/data_access_groups.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/events.jl b/test/api_methods/events.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/events.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/field_names.jl b/test/api_methods/field_names.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/field_names.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/file_repository.jl b/test/api_methods/file_repository.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/file_repository.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/files.jl b/test/api_methods/files.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/files.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/instruments.jl b/test/api_methods/instruments.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/instruments.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/logging.jl b/test/api_methods/logging.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/logging.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/metadata.jl b/test/api_methods/metadata.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/metadata.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/projects.jl b/test/api_methods/projects.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/projects.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/records.jl b/test/api_methods/records.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/records.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/redcap.jl b/test/api_methods/redcap.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/redcap.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/repeating_instruments_and_events.jl b/test/api_methods/repeating_instruments_and_events.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/repeating_instruments_and_events.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/reports.jl b/test/api_methods/reports.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/reports.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/surveys.jl b/test/api_methods/surveys.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/surveys.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/user_roles.jl b/test/api_methods/user_roles.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/user_roles.jl @@ -0,0 +1 @@ + diff --git a/test/api_methods/users.jl b/test/api_methods/users.jl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/api_methods/users.jl @@ -0,0 +1 @@ + diff --git a/test/runtests.jl b/test/runtests.jl index 9224aa4..63870b1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,6 +9,26 @@ if (get(ENV, "REDCAP_API_URL", "")) |> isempty && (get(ENV, "REDCAP_API_TOKEN", @test true else +include("api_methods/arms.jl") +include("api_methods/data_access_groups.jl") +include("api_methods/events.jl") +include("api_methods/field_names.jl") +include("api_methods/file_repository.jl") +include("api_methods/files.jl") +include("api_methods/instruments.jl") +include("api_methods/logging.jl") +include("api_methods/metadata.jl") +include("api_methods/projects.jl") +include("api_methods/records.jl") +include("api_methods/redcap.jl") +include("api_methods/repeating_instruments_and_events.jl") +include("api_methods/reports.jl") +include("api_methods/surveys.jl") +include("api_methods/user_roles.jl") +include("api_methods/users.jl") + + + @test export_version() == "14.5.8" #@test create_project(data="""[{"project_title":"My New REDCap Project","purpose":"0"}]""",format="json") |> REDCap.is_valid_token #TODO: account for running test without token in E From 664da0068be8e8ff40f8a76a205f91041c1cc14b Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:12:14 -0400 Subject: [PATCH 25/28] Convert Dict to CSV, JSON, or XML as needed --- src/api_methods/arms.jl | 2 +- src/api_methods/data_access_groups.jl | 4 ++-- src/api_methods/events.jl | 2 +- src/api_methods/instruments.jl | 2 +- src/api_methods/metadata.jl | 2 +- src/api_methods/projects.jl | 4 ++-- src/api_methods/records.jl | 8 ++++---- src/api_methods/user_roles.jl | 4 ++-- src/api_methods/users.jl | 2 +- src/types.jl | 21 +++++++++++++++------ src/utils.jl | 2 +- test/api_methods/projects.jl | 14 ++++++++++++++ test/runtests.jl | 2 -- 13 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index fc00346..05d4064 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -51,7 +51,7 @@ function import_arms(; override=override, action=REDCap_action(:import), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index df04b50..ee75142 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -63,7 +63,7 @@ function import_DAGs(; content=REDCap_content(:dag), action=REDCap_action(:import), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end @@ -81,7 +81,7 @@ function import_user_DAG_assignment(; token=REDCap_token(token), content=REDCap_content(:userDagMapping), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index 77720be..9bbfa4e 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -52,7 +52,7 @@ function import_events(; content=REDCap_content(:event), action=REDCap_action(:import), override=override, - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), ) end diff --git a/src/api_methods/instruments.jl b/src/api_methods/instruments.jl index ee2e373..04686d7 100644 --- a/src/api_methods/instruments.jl +++ b/src/api_methods/instruments.jl @@ -75,7 +75,7 @@ function import_instrument_event_mappings(; token=REDCap_token(token), content=REDCap_content(:formEventMapping), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/metadata.jl b/src/api_methods/metadata.jl index 5ee73cb..c1431a8 100644 --- a/src/api_methods/metadata.jl +++ b/src/api_methods/metadata.jl @@ -35,7 +35,7 @@ function import_metadata(; token=REDCap_token(token), content=REDCap_content(:metadata), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index a1fa620..2d4249f 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -16,7 +16,7 @@ function create_project(; content=REDCap_content(:project), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), url=REDCap_url(url), token=REDCap_super_token(token), odm=odm, @@ -132,7 +132,7 @@ function import_project_info(; token=REDCap_token(token), content=REDCap_content(:project_settings), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), ) end diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index b0b9442..bac9b0a 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -52,7 +52,7 @@ function export_records(; exportBlankForGrayFormStatus::redcap_bool_input=nothing ) REDCap.request( - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), @@ -83,7 +83,7 @@ function generate_next_record_name( ) REDCap.request( - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:generateNextRecordName), @@ -106,7 +106,7 @@ function import_records(; ) REDCap.request( - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), @@ -130,7 +130,7 @@ function rename_record(; ) REDCap.request( - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), url=REDCap_url(url), token=REDCap_token(token), content=REDCap_content(:record), diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index e17e660..e3baee8 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -49,7 +49,7 @@ function import_user_roles(; token=REDCap_token(token), content=REDCap_content(:userRole), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end @@ -84,7 +84,7 @@ function import_user_role_assignments(; token=REDCap_token(token), content=REDCap_content(:userRoleMapping), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index 121ee5a..2c0961a 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -53,7 +53,7 @@ function import_users(; token=REDCap_token(token), content=REDCap_content(:user), format=REDCap_format(format), - data=REDCap_data(data), + data=REDCap_data(data,REDCap_format(format)), returnFormat=REDCap_format(returnFormat), ) end diff --git a/src/types.jl b/src/types.jl index 4609a3a..3bdbc3d 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,9 +1,4 @@ -#TODO: consier passing data and format and converting data based on format -const redcap_data_input = Union{String, Dict} -REDCap_data(x::Dict)="[$(JSON.json(x))]" -REDCap_data(x::String)=read(x, String) - struct REDCap_action id::Symbol REDCap_action(id) = id ∈ [:createFolder,:delete,:export,:import,:list,:rename,:switch] ? new(id) : throw(ArgumentError("Invalid action parameter")) @@ -27,9 +22,9 @@ REDCap_url(x::redcap_url_input) = occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.U const redcap_token_input = String const redcap_super_token_input = String +const redcap_data_input = Union{String, Dict} const redcap_filterLogic_input = Union{String, Nothing} const redcap_odm_input = Union{String, Nothing} - const redcap_array_input = Union{Array, Nothing} const redcap_bool_input = Union{Bool, Nothing} const redcap_format_input = Union{String, Symbol, Nothing} @@ -61,6 +56,20 @@ Base.display(x::REDCap_format) = Base.display(x.id) Base.string(x::REDCap_format) = Base.string(x.id) Base.convert(String,x::REDCap_format) = string(x) +function REDCap_data(x::Dict, format::Union{REDCap_format, Nothing}) + return if format == REDCap_format(:json) + "[$(JSON.json(x))]" + elseif format == REDCap_format(:csv) + join(keys(x),',') * "\n" * join(values(x),',') + else + "" + "" * + join(["<$k>$v" for (k,v) in x]) * + "" + end +end +REDCap_data(x::String, format::REDCap_format) = read(x, String) + struct REDCap_token id::String REDCap_token(id) = occursin(r"^[0-9A-F]{32}([0-9A-F]{32})?$", id) ? new(id) : throw(ArgumentError("Invalid REDCap token")) diff --git a/src/utils.jl b/src/utils.jl index 836e91d..700b623 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -14,7 +14,7 @@ function request(; #TODO: Can't the data parameter be nothing and still hav an effect in at least 1 function? if !isnothing(data); html_request_body["data"] = "$data" end - #println(html_request_body) + println("Posting the following (token not shown): ", filter(x->(first(x)!="token"), html_request_body)) response = HTTP.post( URI(url); diff --git a/test/api_methods/projects.jl b/test/api_methods/projects.jl index 8b13789..86dcdad 100644 --- a/test/api_methods/projects.jl +++ b/test/api_methods/projects.jl @@ -1 +1,15 @@ +@test_throws UndefKeywordError create_project() + +@test create_project(data = Dict(:project_title => "AAA", "purpose" => 1),format=:csv) == +"ERROR: You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other)." + +@test create_project(data = Dict(:project_title => "AAA", "purpose" => 1),format=:json) == +"{\"error\":\"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other).\"}" + +@test create_project(data = Dict(:project_title => "AAA", "purpose" => 1),format=:xml) == +"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other)." + +@test create_project(data = Dict(:project_title => "AAA", "purpose" => 1)) == +"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other)." + diff --git a/test/runtests.jl b/test/runtests.jl index 63870b1..0cc3f71 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -30,7 +30,6 @@ include("api_methods/users.jl") @test export_version() == "14.5.8" -#@test create_project(data="""[{"project_title":"My New REDCap Project","purpose":"0"}]""",format="json") |> REDCap.is_valid_token #TODO: account for running test without token in E #TODO: more tests like this, checking the API's return value @@ -45,7 +44,6 @@ import_users(data="""username\naharris""", format=:csv) begin #TODO: for now, put a :json format tag when using a Dict - @test create_project(format=:json,data=Dict(:project_title=>"AAA","purpose"=>1)) == "{\"error\":\"You must provide some text for 'purpose_other' since you specified 'purpose' as '1' (Other).\"}" project_token = create_project(format=:json,data=Dict(:project_title=>"$(now())",:purpose=>0)) export_project_XML(token=project_token) export_project_info(token=project_token) From fd0bc3d8b476e76017da1de9a56b48c019d4f68c Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:29:54 -0400 Subject: [PATCH 26/28] Put post request (minus token) in debug message --- src/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index 700b623..32875e7 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -14,7 +14,7 @@ function request(; #TODO: Can't the data parameter be nothing and still hav an effect in at least 1 function? if !isnothing(data); html_request_body["data"] = "$data" end - println("Posting the following (token not shown): ", filter(x->(first(x)!="token"), html_request_body)) + @debug(filter(x->(first(x)!="token"), html_request_body)) response = HTTP.post( URI(url); From a0729039ea6d595f2c7fd6da96cd5a7a1a25f4cb Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 17:31:38 -0400 Subject: [PATCH 27/28] Clean up types --- src/types.jl | 53 +++++++++++++++++++++++++++++----------------------- src/utils.jl | 3 +++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/types.jl b/src/types.jl index 3bdbc3d..c9e872e 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,3 +1,31 @@ +#TODO: Should some of these functions be moved to src/utils.jl? +#TODO: separate into modules + +# Any types that users may pass to a function named after a REDCap method +const redcap_token_input = String +const redcap_super_token_input = redcap_token_input +const redcap_data_input = Union{String, Dict} #TODO: there might be 1 REDCap method where Dict can be nothing, but passing it as an argument has an effect +const redcap_filterLogic_input = Union{String, Nothing} +const redcap_odm_input = Union{String, Nothing} +const redcap_array_input = Union{Array, Nothing} +const redcap_bool_input = Union{Bool, Nothing} +const redcap_format_input = Union{String, Symbol, Nothing} +const redcap_returnFormat_input = redcap_format_input +const redcap_timestamp_input = Union{Date, DateTime, String,Nothing} + +const redcap_generic_input = Union{ + redcap_data_input, + redcap_filterLogic_input, + redcap_odm_input, + redcap_array_input, + redcap_bool_input, + redcap_format_input, + redcap_timestamp_input, + } + +# Any types that are used internally by REDCap.jl +# These are used primarily for coherency checks, so +# any functions that fulfill this sort of role are included. struct REDCap_action id::Symbol @@ -20,32 +48,11 @@ const redcap_url_input = String # Maybe a function that checks for common mistakes REDCap_url(x::redcap_url_input) = occursin(r"^https:\/\/.*\/api\/$", x) ? URIs.URI(x) : throw(ArgumentError("Invalid REDCap url")) -const redcap_token_input = String -const redcap_super_token_input = String -const redcap_data_input = Union{String, Dict} -const redcap_filterLogic_input = Union{String, Nothing} -const redcap_odm_input = Union{String, Nothing} -const redcap_array_input = Union{Array, Nothing} -const redcap_bool_input = Union{Bool, Nothing} -const redcap_format_input = Union{String, Symbol, Nothing} -const redcap_returnFormat_input = redcap_format_input - -const redcap_timestamp_input = Union{Date, DateTime, String,Nothing} REDCap_datetime(x::String) = DateTime(x,"yyyy-m-dd H:M") REDCap_datetime(x::Date) = DateTime(x) REDCap_datetime(x::DateTime) = x REDCap_datetime(x::Nothing) = nothing -redcap_generic_input = Union{ - redcap_data_input, - redcap_filterLogic_input, - redcap_odm_input, - redcap_array_input, - redcap_bool_input, - redcap_format_input, - redcap_timestamp_input, - } - struct REDCap_format id::redcap_format_input REDCap_format(id::Symbol) = id ∈ [:csv,:json,:xml] ? new(id) : throw(ArgumentError("Invalid format parameter")) @@ -71,7 +78,7 @@ end REDCap_data(x::String, format::REDCap_format) = read(x, String) struct REDCap_token - id::String + id::redcap_token_input REDCap_token(id) = occursin(r"^[0-9A-F]{32}([0-9A-F]{32})?$", id) ? new(id) : throw(ArgumentError("Invalid REDCap token")) end Base.display(x::REDCap_token) = display(x.id) @@ -79,7 +86,7 @@ Base.string(x::REDCap_token) = string(x.id) Base.convert(String,x::REDCap_token) = string(x) struct REDCap_super_token - id::String + id::redcap_super_token_input REDCap_super_token(id) = occursin(r"^[0-9A-F]{64}$", id) ? new(id) : throw(ArgumentError("Invalid REDCap super token")) end Base.display(x::REDCap_super_token) = display(x.id) diff --git a/src/utils.jl b/src/utils.jl index 32875e7..f04430b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -14,6 +14,9 @@ function request(; #TODO: Can't the data parameter be nothing and still hav an effect in at least 1 function? if !isnothing(data); html_request_body["data"] = "$data" end + + #TODO: make this clear to users + #ENV["JULIA_DEBUG"] = REDCap @debug(filter(x->(first(x)!="token"), html_request_body)) response = HTTP.post( From 154f2517a42994571cdd8368b5917c50982d2943 Mon Sep 17 00:00:00 2001 From: AshlinHarris <90787010+AshlinHarris@users.noreply.github.com> Date: Sat, 24 Aug 2024 17:41:25 -0400 Subject: [PATCH 28/28] Add TagBot.yml --- src/.github/workflows/TagBot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/.github/workflows/TagBot.yml diff --git a/src/.github/workflows/TagBot.yml b/src/.github/workflows/TagBot.yml new file mode 100644 index 0000000..f389611 --- /dev/null +++ b/src/.github/workflows/TagBot.yml @@ -0,0 +1,20 @@ +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: + inputs: + lookback: + default: 3 +permissions: + contents: write +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }}